/*
 * COPYRIGHT:       GPL - See COPYING in the top level directory
 * PROJECT:         ReactOS Virtual DOS Machine
 * FILE:            subsystems/mvdm/ntvdm/bios/vidbios.c
 * PURPOSE:         VDM 32-bit Video BIOS Support Library
 * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
 *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
 */

/* INCLUDES *******************************************************************/

#include "ntvdm.h"

#define NDEBUG
#include <debug.h>

/* BIOS Version number and Copyright */
#include <reactos/buildno.h>
#include <reactos/version.h>

#include "emulator.h"
#include "cpu/cpu.h"
#include "cpu/bop.h"
#include "memory.h"

#include "bios.h"
#include "bios32/bios32p.h"
#include "rom.h"
#include "bios32/vbe.h"
// #include "vidbios.h"
#include "bios32/vidbios32.h"

#include "io.h"
#include "hardware/video/svga.h"
/**/
#include "../console/video.h"
/**/

/* PRIVATE VARIABLES **********************************************************/

/*
 * WARNING! For compatibility purposes the string "IBM" should be at C000:001E.
 */
static const CHAR BiosInfo[] =
    "00000000000 Emulation of IBM VGA Compatible ROM\0"
    "CL-GD5434 VGA BIOS Version 1.41  \r\n"
    "Copyright (C) ReactOS Team 1996-"COPYRIGHT_YEAR"\r\n"
    "The original CL-GD5434 card was created by Cirrus Logic, Inc.\r\n\0"
    "BIOS Date: 06/17/13\0";

C_ASSERT(sizeof(BiosInfo)-1 <= 0xFF-0x05); // Ensures that we won't overflow on the Video Code


/*
 * VGA Register Configurations for BIOS Video Modes.
 * The configurations were checked against SeaBIOS VGA BIOS.
 */

static VGA_REGISTERS VideoMode_40x25_text =
{
    /* Miscellaneous Register */
    0x67,

    /* Sequencer Registers */
    {0x00, 0x08, 0x03, 0x00, 0x02},

    /* CRTC Registers */                /* CGA-compatible: 0xC7, 0x06, 0x07 */
    {0x2D, 0x27, 0x28, 0x90, 0x2B, 0xA0, 0xBF, 0x1F, 0x00, 0x4F, 0x0D, 0x0E,
     0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x1F, 0x96, 0xB9, 0xA3,
     0xFF},

    /* GC Registers */
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0F, 0xFF},

    /* AC Registers */
    {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
     0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x00, 0x0F, 0x08, 0x00}
};

static VGA_REGISTERS VideoMode_80x25_text =
{
    /* Miscellaneous Register */
    0x67,

    /* Sequencer Registers */
    {0x00, 0x00, 0x03, 0x00, 0x02},

    /* CRTC Registers */                /* CGA-compatible: 0xC7, 0x06, 0x07 */
    {0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81, 0xBF, 0x1F, 0x00, 0x4F, 0x0D, 0x0E,
     0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3,
     0xFF},

    /* GC Registers */
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0F, 0xFF},

    /* AC Registers */
    {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
     0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x00, 0x0F, 0x08, 0x00}
};

static VGA_REGISTERS VideoMode_320x200_4color =
{
    /* Miscellaneous Register */
    0x63,

    /* Sequencer Registers */
    {0x00, 0x09, 0x03, 0x00, 0x02},

    /* CRTC Registers */
    {0x2D, 0x27, 0x28, 0x90, 0x2B, 0x80, 0xBF, 0x1F, 0x00, 0xC1, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x00, 0x96, 0xB9, 0xA2,
     0xFF},

    /* GC Registers */
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0F, 0x0F, 0xFF},

    /* AC Registers */
    {0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
     0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x03, 0x00, 0x00}
};

static VGA_REGISTERS VideoMode_640x200_2color =
{
    /* Miscellaneous Register */
    0x63,

    /* Sequencer Registers */
    {0x00, 0x01, 0x01, 0x00, 0x02},

    /* CRTC Registers */
    {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0xC1, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x00, 0x96, 0xB9, 0xC2,
     0xFF},

    /* GC Registers */
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0xFF},

    /* AC Registers */
    {0x00, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
     0x17, 0x17, 0x17, 0x17, 0x01, 0x00, 0x01, 0x00, 0x00}
};

static VGA_REGISTERS VideoMode_320x200_16color =
{
    /* Miscellaneous Register */
    0x63,

    /* Sequencer Registers */
    {0x00, 0x09, 0x0F, 0x00, 0x06},

    /* CRTC Registers */
    {0x2D, 0x27, 0x28, 0x90, 0x2B, 0x80, 0xBF, 0x1F, 0x00, 0xC0, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x00, 0x96, 0xB9, 0xE3,
     0xFF},

    /* GC Registers */
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},

    /* AC Registers */
    {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
     0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00}
};

static VGA_REGISTERS VideoMode_640x200_16color =
{
    /* Miscellaneous Register */
    0x63,

    /* Sequencer Registers */
    {0x00, 0x01, 0x0F, 0x00, 0x06},

    /* CRTC Registers */
    {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0xC0, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x00, 0x96, 0xB9, 0xE3,
     0xFF},

    /* GC Registers */
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},

    /* AC Registers */
    {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
     0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x0F, 0x00, 0x00}
};

static VGA_REGISTERS VideoMode_640x350_16color =
{
    /* Miscellaneous Register */
    0xA3,

    /* Sequencer Registers */
    {0x00, 0x01, 0x0F, 0x00, 0x06},

    /* CRTC Registers */
    {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x40, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x83, 0x85, 0x5D, 0x28, 0x0F, 0x63, 0xBA, 0xE3,
     0xFF},

    /* GC Registers */
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},

    /* AC Registers */
    {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
     0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
};

static VGA_REGISTERS VideoMode_640x480_2color =
{
    /* Miscellaneous Register */
    0xE3,

    /* Sequencer Registers */
    {0x00, 0x01, 0x0F, 0x00, 0x06},

    /* CRTC Registers */
    {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xC3,
     0xFF},

    /* GC Registers */
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},

    /* AC Registers */
//     {0x00, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
//      0x3F, 0x3F, 0x3F, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
    {0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3F,
     0x00, 0x3F, 0x00, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
};

static VGA_REGISTERS VideoMode_640x480_16color =
{
    /* Miscellaneous Register */
    0xE3,

    /* Sequencer Registers */
    {0x00, 0x01, 0x0F, 0x00, 0x06},

    /* CRTC Registers */
    {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0xEA, 0x8C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3,
     0xFF},

    /* GC Registers */
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F, 0xFF},

    /* AC Registers */
    {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B,
     0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00}
};

static VGA_REGISTERS VideoMode_320x200_256color =
{
    /* Miscellaneous Register */
    0x63,

    /* Sequencer Registers */
    {0x00, 0x01, 0x0F, 0x00, 0x0E},

    /* CRTC Registers */
    {0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x41, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3,
     0xFF},

    /* GC Registers */
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF},

    /* AC Registers */
    {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
     0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00}
};


/*
 * BIOS Mode Palettes
 *
 * Many people have different versions of those palettes
 * (e.g. DOSBox, http://www.brokenthorn.com/Resources/OSDevVid2.html ,
 * etc...) A choice should be made at some point.
 */

#if 0

// This is the same as EgaPalette__HiRes
// Unused at the moment
static CONST COLORREF TextPalette[VGA_MAX_COLORS / 4] =
{
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0xAA, 0x00), RGB(0xAA, 0xAA, 0xAA),
    RGB(0x00, 0x00, 0x55), RGB(0x00, 0x00, 0xFF), RGB(0x00, 0xAA, 0x55), RGB(0x00, 0xAA, 0xFF),
    RGB(0xAA, 0x00, 0x55), RGB(0xAA, 0x00, 0xFF), RGB(0xAA, 0xAA, 0x55), RGB(0xAA, 0xAA, 0xFF),

    RGB(0x00, 0x55, 0x00), RGB(0x00, 0x55, 0xAA), RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0xAA),
    RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0x55, 0xAA), RGB(0xAA, 0xFF, 0x00), RGB(0xAA, 0xFF, 0xAA),
    RGB(0x00, 0x55, 0x55), RGB(0x00, 0x55, 0xFF), RGB(0x00, 0xFF, 0x55), RGB(0x00, 0xFF, 0xFF),
    RGB(0xAA, 0x55, 0x55), RGB(0xAA, 0x55, 0xFF), RGB(0xAA, 0xFF, 0x55), RGB(0xAA, 0xFF, 0xFF),


    RGB(0x55, 0x00, 0x00), RGB(0x55, 0x00, 0xAA), RGB(0x55, 0xAA, 0x00), RGB(0x55, 0xAA, 0xAA),
    RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x00, 0xAA), RGB(0xFF, 0xAA, 0x00), RGB(0xFF, 0xAA, 0xAA),
    RGB(0x55, 0x00, 0x55), RGB(0x55, 0x00, 0xFF), RGB(0x55, 0xAA, 0x55), RGB(0x55, 0xAA, 0xFF),
    RGB(0xFF, 0x00, 0x55), RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0xAA, 0x55), RGB(0xFF, 0xAA, 0xFF),

    RGB(0x55, 0x55, 0x00), RGB(0x55, 0x55, 0xAA), RGB(0x55, 0xFF, 0x00), RGB(0x55, 0xFF, 0xAA),
    RGB(0xFF, 0x55, 0x00), RGB(0xFF, 0x55, 0xAA), RGB(0xFF, 0xFF, 0x00), RGB(0xFF, 0xFF, 0xAA),
    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
};

// Unused at the moment
static CONST COLORREF mtext_palette[64] =
{
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
    RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
    RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),

    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
    RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
    RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF)
};

// Unused at the moment
static CONST COLORREF mtext_s3_palette[64] =
{
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
    RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
    RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),

    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
    RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA), RGB(0xAA, 0xAA, 0xAA),
    RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF),
    RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF), RGB(0xFF, 0xFF, 0xFF)
};

// Unused at the moment
static CONST COLORREF CgaPalette[16] =
{
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
};

/* CGA palette 1 */
static CONST BYTE CgaPalette1[] =
{
    0x00,   /* 0 - Black  */
    0x03,   /* 1 - Cyan   */
    0x05,   /* 2- Magenta */
    0x07,   /* 3 - White  */
}

/* CGA palette 1 bright */
static CONST BYTE CgaPalette1i[] =
{
    0x00,   /* 0 - Black         */
    0x13,   /* 1 - Light cyan    */
    0x15,   /* 2 - Light magenta */
    0x17,   /* 3 - Bright White  */
};

/* CGA palette 2 */
static CONST BYTE CgaPalette2[] =
{
    0x00,   /* 0 - Black */
    0x02,   /* 1 - Green */
    0x04,   /* 2 - Red   */
    0x06,   /* 3 - Brown */
};

/* CGA palette 2 bright */
static CONST BYTE CgaPalette2i[] =
{
    0x00,   /* 0 - Black       */
    0x12,   /* 1 - Light green */
    0x14,   /* 2 - Light red   */
    0x16,   /* 3 - Yellow      */
};

// Unused at the moment; same palette as EgaPalette__16Colors
static CONST COLORREF CgaPalette2[VGA_MAX_COLORS / 4] =
{
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),

    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),

    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),

    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
};

#endif

static CONST COLORREF EgaPalette__16Colors[VGA_MAX_COLORS / 4] =
{
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),

    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),


    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),

    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),



    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),

    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),


    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),

    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
};

// This is the same as TextPalette
static CONST COLORREF EgaPalette__HiRes[VGA_MAX_COLORS / 4] =
{
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0xAA, 0x00), RGB(0xAA, 0xAA, 0xAA),
    RGB(0x00, 0x00, 0x55), RGB(0x00, 0x00, 0xFF), RGB(0x00, 0xAA, 0x55), RGB(0x00, 0xAA, 0xFF),
    RGB(0xAA, 0x00, 0x55), RGB(0xAA, 0x00, 0xFF), RGB(0xAA, 0xAA, 0x55), RGB(0xAA, 0xAA, 0xFF),

    RGB(0x00, 0x55, 0x00), RGB(0x00, 0x55, 0xAA), RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0xAA),
    RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0x55, 0xAA), RGB(0xAA, 0xFF, 0x00), RGB(0xAA, 0xFF, 0xAA),
    RGB(0x00, 0x55, 0x55), RGB(0x00, 0x55, 0xFF), RGB(0x00, 0xFF, 0x55), RGB(0x00, 0xFF, 0xFF),
    RGB(0xAA, 0x55, 0x55), RGB(0xAA, 0x55, 0xFF), RGB(0xAA, 0xFF, 0x55), RGB(0xAA, 0xFF, 0xFF),


    RGB(0x55, 0x00, 0x00), RGB(0x55, 0x00, 0xAA), RGB(0x55, 0xAA, 0x00), RGB(0x55, 0xAA, 0xAA),
    RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x00, 0xAA), RGB(0xFF, 0xAA, 0x00), RGB(0xFF, 0xAA, 0xAA),
    RGB(0x55, 0x00, 0x55), RGB(0x55, 0x00, 0xFF), RGB(0x55, 0xAA, 0x55), RGB(0x55, 0xAA, 0xFF),
    RGB(0xFF, 0x00, 0x55), RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0xAA, 0x55), RGB(0xFF, 0xAA, 0xFF),

    RGB(0x55, 0x55, 0x00), RGB(0x55, 0x55, 0xAA), RGB(0x55, 0xFF, 0x00), RGB(0x55, 0xFF, 0xAA),
    RGB(0xFF, 0x55, 0x00), RGB(0xFF, 0x55, 0xAA), RGB(0xFF, 0xFF, 0x00), RGB(0xFF, 0xFF, 0xAA),
    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF)
};

#define USE_REACTOS_COLORS
// #define USE_DOSBOX_COLORS

/*
 * Same palette as the default one 'VgaDefaultPalette' in vga.c
 */
#if defined(USE_REACTOS_COLORS)

// ReactOS colors
static CONST COLORREF VgaPalette[VGA_MAX_COLORS] =
{
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
    RGB(0x00, 0x00, 0x00), RGB(0x10, 0x10, 0x10), RGB(0x20, 0x20, 0x20), RGB(0x35, 0x35, 0x35),
    RGB(0x45, 0x45, 0x45), RGB(0x55, 0x55, 0x55), RGB(0x65, 0x65, 0x65), RGB(0x75, 0x75, 0x75),
    RGB(0x8A, 0x8A, 0x8A), RGB(0x9A, 0x9A, 0x9A), RGB(0xAA, 0xAA, 0xAA), RGB(0xBA, 0xBA, 0xBA),
    RGB(0xCA, 0xCA, 0xCA), RGB(0xDF, 0xDF, 0xDF), RGB(0xEF, 0xEF, 0xEF), RGB(0xFF, 0xFF, 0xFF),
    RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x82, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF),
    RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x82), RGB(0xFF, 0x00, 0x41),
    RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x82, 0x00), RGB(0xFF, 0xBE, 0x00),
    RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x82, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00),
    RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x82), RGB(0x00, 0xFF, 0xBE),
    RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x82, 0xFF), RGB(0x00, 0x41, 0xFF),
    RGB(0x82, 0x82, 0xFF), RGB(0x9E, 0x82, 0xFF), RGB(0xBE, 0x82, 0xFF), RGB(0xDF, 0x82, 0xFF),
    RGB(0xFF, 0x82, 0xFF), RGB(0xFF, 0x82, 0xDF), RGB(0xFF, 0x82, 0xBE), RGB(0xFF, 0x82, 0x9E),
    RGB(0xFF, 0x82, 0x82), RGB(0xFF, 0x9E, 0x82), RGB(0xFF, 0xBE, 0x82), RGB(0xFF, 0xDF, 0x82),
    RGB(0xFF, 0xFF, 0x82), RGB(0xDF, 0xFF, 0x82), RGB(0xBE, 0xFF, 0x82), RGB(0x9E, 0xFF, 0x82),
    RGB(0x82, 0xFF, 0x82), RGB(0x82, 0xFF, 0x9E), RGB(0x82, 0xFF, 0xBE), RGB(0x82, 0xFF, 0xDF),
    RGB(0x82, 0xFF, 0xFF), RGB(0x82, 0xDF, 0xFF), RGB(0x82, 0xBE, 0xFF), RGB(0x82, 0x9E, 0xFF),
    RGB(0xBA, 0xBA, 0xFF), RGB(0xCA, 0xBA, 0xFF), RGB(0xDF, 0xBA, 0xFF), RGB(0xEF, 0xBA, 0xFF),
    RGB(0xFF, 0xBA, 0xFF), RGB(0xFF, 0xBA, 0xEF), RGB(0xFF, 0xBA, 0xDF), RGB(0xFF, 0xBA, 0xCA),
    RGB(0xFF, 0xBA, 0xBA), RGB(0xFF, 0xCA, 0xBA), RGB(0xFF, 0xDF, 0xBA), RGB(0xFF, 0xEF, 0xBA),
    RGB(0xFF, 0xFF, 0xBA), RGB(0xEF, 0xFF, 0xBA), RGB(0xDF, 0xFF, 0xBA), RGB(0xCA, 0xFF, 0xBA),
    RGB(0xBA, 0xFF, 0xBA), RGB(0xBA, 0xFF, 0xCA), RGB(0xBA, 0xFF, 0xDF), RGB(0xBA, 0xFF, 0xEF),
    RGB(0xBA, 0xFF, 0xFF), RGB(0xBA, 0xEF, 0xFF), RGB(0xBA, 0xDF, 0xFF), RGB(0xBA, 0xCA, 0xFF),
    RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x39, 0x00, 0x71), RGB(0x55, 0x00, 0x71),
    RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x39), RGB(0x71, 0x00, 0x1C),
    RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x39, 0x00), RGB(0x71, 0x55, 0x00),
    RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x39, 0x71, 0x00), RGB(0x1C, 0x71, 0x00),
    RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x39), RGB(0x00, 0x71, 0x55),
    RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x39, 0x71), RGB(0x00, 0x1C, 0x71),
    RGB(0x39, 0x39, 0x71), RGB(0x45, 0x39, 0x71), RGB(0x55, 0x39, 0x71), RGB(0x61, 0x39, 0x71),
    RGB(0x71, 0x39, 0x71), RGB(0x71, 0x39, 0x61), RGB(0x71, 0x39, 0x55), RGB(0x71, 0x39, 0x45),
    RGB(0x71, 0x39, 0x39), RGB(0x71, 0x45, 0x39), RGB(0x71, 0x55, 0x39), RGB(0x71, 0x61, 0x39),
    RGB(0x71, 0x71, 0x39), RGB(0x61, 0x71, 0x39), RGB(0x55, 0x71, 0x39), RGB(0x45, 0x71, 0x39),
    RGB(0x39, 0x71, 0x39), RGB(0x39, 0x71, 0x45), RGB(0x39, 0x71, 0x55), RGB(0x39, 0x71, 0x61),
    RGB(0x39, 0x71, 0x71), RGB(0x39, 0x61, 0x71), RGB(0x39, 0x55, 0x71), RGB(0x39, 0x45, 0x71),
    RGB(0x51, 0x51, 0x71), RGB(0x59, 0x51, 0x71), RGB(0x61, 0x51, 0x71), RGB(0x69, 0x51, 0x71),
    RGB(0x71, 0x51, 0x71), RGB(0x71, 0x51, 0x69), RGB(0x71, 0x51, 0x61), RGB(0x71, 0x51, 0x59),
    RGB(0x71, 0x51, 0x51), RGB(0x71, 0x59, 0x51), RGB(0x71, 0x61, 0x51), RGB(0x71, 0x69, 0x51),
    RGB(0x71, 0x71, 0x51), RGB(0x69, 0x71, 0x51), RGB(0x61, 0x71, 0x51), RGB(0x59, 0x71, 0x51),
    RGB(0x51, 0x71, 0x51), RGB(0x51, 0x71, 0x59), RGB(0x51, 0x71, 0x61), RGB(0x51, 0x71, 0x69),
    RGB(0x51, 0x71, 0x71), RGB(0x51, 0x69, 0x71), RGB(0x51, 0x61, 0x71), RGB(0x51, 0x59, 0x71),
    RGB(0x00, 0x00, 0x41), RGB(0x10, 0x00, 0x41), RGB(0x20, 0x00, 0x41), RGB(0x31, 0x00, 0x41),
    RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x31), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10),
    RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x31, 0x00),
    RGB(0x41, 0x41, 0x00), RGB(0x31, 0x41, 0x00), RGB(0x20, 0x41, 0x00), RGB(0x10, 0x41, 0x00),
    RGB(0x00, 0x41, 0x00), RGB(0x00, 0x41, 0x10), RGB(0x00, 0x41, 0x20), RGB(0x00, 0x41, 0x31),
    RGB(0x00, 0x41, 0x41), RGB(0x00, 0x31, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41),
    RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x31, 0x20, 0x41), RGB(0x39, 0x20, 0x41),
    RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x39), RGB(0x41, 0x20, 0x31), RGB(0x41, 0x20, 0x28),
    RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x31, 0x20), RGB(0x41, 0x39, 0x20),
    RGB(0x41, 0x41, 0x20), RGB(0x39, 0x41, 0x20), RGB(0x31, 0x41, 0x20), RGB(0x28, 0x41, 0x20),
    RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x31), RGB(0x20, 0x41, 0x39),
    RGB(0x20, 0x41, 0x41), RGB(0x20, 0x39, 0x41), RGB(0x20, 0x31, 0x41), RGB(0x20, 0x28, 0x41),
    RGB(0x2D, 0x2D, 0x41), RGB(0x31, 0x2D, 0x41), RGB(0x35, 0x2D, 0x41), RGB(0x3D, 0x2D, 0x41),
    RGB(0x41, 0x2D, 0x41), RGB(0x41, 0x2D, 0x3D), RGB(0x41, 0x2D, 0x35), RGB(0x41, 0x2D, 0x31),
    RGB(0x41, 0x2D, 0x2D), RGB(0x41, 0x31, 0x2D), RGB(0x41, 0x35, 0x2D), RGB(0x41, 0x3D, 0x2D),
    RGB(0x41, 0x41, 0x2D), RGB(0x3D, 0x41, 0x2D), RGB(0x35, 0x41, 0x2D), RGB(0x31, 0x41, 0x2D),
    RGB(0x2D, 0x41, 0x2D), RGB(0x2D, 0x41, 0x31), RGB(0x2D, 0x41, 0x35), RGB(0x2D, 0x41, 0x3D),
    RGB(0x2D, 0x41, 0x41), RGB(0x2D, 0x3D, 0x41), RGB(0x2D, 0x35, 0x41), RGB(0x2D, 0x31, 0x41),
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00)
};

#elif defined(USE_DOSBOX_COLORS)

// DOSBox colors
static CONST COLORREF VgaPalette[VGA_MAX_COLORS] =
{
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0xAA), RGB(0x00, 0xAA, 0x00), RGB(0x00, 0xAA, 0xAA),
    RGB(0xAA, 0x00, 0x00), RGB(0xAA, 0x00, 0xAA), RGB(0xAA, 0x55, 0x00), RGB(0xAA, 0xAA, 0xAA),
    RGB(0x55, 0x55, 0x55), RGB(0x55, 0x55, 0xFF), RGB(0x55, 0xFF, 0x55), RGB(0x55, 0xFF, 0xFF),
    RGB(0xFF, 0x55, 0x55), RGB(0xFF, 0x55, 0xFF), RGB(0xFF, 0xFF, 0x55), RGB(0xFF, 0xFF, 0xFF),
    RGB(0x00, 0x00, 0x00), RGB(0x14, 0x14, 0x14), RGB(0x20, 0x20, 0x20), RGB(0x2C, 0x2C, 0x2C),
    RGB(0x38, 0x38, 0x38), RGB(0x45, 0x45, 0x45), RGB(0x51, 0x51, 0x51), RGB(0x61, 0x61, 0x61),
    RGB(0x71, 0x71, 0x71), RGB(0x82, 0x82, 0x82), RGB(0x92, 0x92, 0x92), RGB(0xA2, 0xA2, 0xA2),
    RGB(0xB6, 0xB6, 0xB6), RGB(0xCB, 0xCB, 0xCB), RGB(0xE3, 0xE3, 0xE3), RGB(0xFF, 0xFF, 0xFF),
    RGB(0x00, 0x00, 0xFF), RGB(0x41, 0x00, 0xFF), RGB(0x7D, 0x00, 0xFF), RGB(0xBE, 0x00, 0xFF),
    RGB(0xFF, 0x00, 0xFF), RGB(0xFF, 0x00, 0xBE), RGB(0xFF, 0x00, 0x7D), RGB(0xFF, 0x00, 0x41),
    RGB(0xFF, 0x00, 0x00), RGB(0xFF, 0x41, 0x00), RGB(0xFF, 0x7D, 0x00), RGB(0xFF, 0xBE, 0x00),
    RGB(0xFF, 0xFF, 0x00), RGB(0xBE, 0xFF, 0x00), RGB(0x7D, 0xFF, 0x00), RGB(0x41, 0xFF, 0x00),
    RGB(0x00, 0xFF, 0x00), RGB(0x00, 0xFF, 0x41), RGB(0x00, 0xFF, 0x7D), RGB(0x00, 0xFF, 0xBE),
    RGB(0x00, 0xFF, 0xFF), RGB(0x00, 0xBE, 0xFF), RGB(0x00, 0x7D, 0xFF), RGB(0x00, 0x41, 0xFF),
    RGB(0x7D, 0x7D, 0xFF), RGB(0x9E, 0x7D, 0xFF), RGB(0xBE, 0x7D, 0xFF), RGB(0xDF, 0x7D, 0xFF),
    RGB(0xFF, 0x7D, 0xFF), RGB(0xFF, 0x7D, 0xDF), RGB(0xFF, 0x7D, 0xBE), RGB(0xFF, 0x7D, 0x9E),

    RGB(0xFF, 0x7D, 0x7D), RGB(0xFF, 0x9E, 0x7D), RGB(0xFF, 0xBE, 0x7D), RGB(0xFF, 0xDF, 0x7D),
    RGB(0xFF, 0xFF, 0x7D), RGB(0xDF, 0xFF, 0x7D), RGB(0xBE, 0xFF, 0x7D), RGB(0x9E, 0xFF, 0x7D),
    RGB(0x7D, 0xFF, 0x7D), RGB(0x7D, 0xFF, 0x9E), RGB(0x7D, 0xFF, 0xBE), RGB(0x7D, 0xFF, 0xDF),
    RGB(0x7D, 0xFF, 0xFF), RGB(0x7D, 0xDF, 0xFF), RGB(0x7D, 0xBE, 0xFF), RGB(0x7D, 0x9E, 0xFF),
    RGB(0xB6, 0xB6, 0xFF), RGB(0xC7, 0xB6, 0xFF), RGB(0xDB, 0xB6, 0xFF), RGB(0xEB, 0xB6, 0xFF),
    RGB(0xFF, 0xB6, 0xFF), RGB(0xFF, 0xB6, 0xEB), RGB(0xFF, 0xB6, 0xDB), RGB(0xFF, 0xB6, 0xC7),
    RGB(0xFF, 0xB6, 0xB6), RGB(0xFF, 0xC7, 0xB6), RGB(0xFF, 0xDB, 0xB6), RGB(0xFF, 0xEB, 0xB6),
    RGB(0xFF, 0xFF, 0xB6), RGB(0xEB, 0xFF, 0xB6), RGB(0xDB, 0xFF, 0xB6), RGB(0xC7, 0xFF, 0xB6),
    RGB(0xB6, 0xFF, 0xB6), RGB(0xB6, 0xFF, 0xC7), RGB(0xB6, 0xFF, 0xDB), RGB(0xB6, 0xFF, 0xEB),
    RGB(0xB6, 0xFF, 0xFF), RGB(0xB6, 0xEB, 0xFF), RGB(0xB6, 0xDB, 0xFF), RGB(0xB6, 0xC7, 0xFF),
    RGB(0x00, 0x00, 0x71), RGB(0x1C, 0x00, 0x71), RGB(0x38, 0x00, 0x71), RGB(0x55, 0x00, 0x71),
    RGB(0x71, 0x00, 0x71), RGB(0x71, 0x00, 0x55), RGB(0x71, 0x00, 0x38), RGB(0x71, 0x00, 0x1C),
    RGB(0x71, 0x00, 0x00), RGB(0x71, 0x1C, 0x00), RGB(0x71, 0x38, 0x00), RGB(0x71, 0x55, 0x00),
    RGB(0x71, 0x71, 0x00), RGB(0x55, 0x71, 0x00), RGB(0x38, 0x71, 0x00), RGB(0x1C, 0x71, 0x00),
    RGB(0x00, 0x71, 0x00), RGB(0x00, 0x71, 0x1C), RGB(0x00, 0x71, 0x38), RGB(0x00, 0x71, 0x55),
    RGB(0x00, 0x71, 0x71), RGB(0x00, 0x55, 0x71), RGB(0x00, 0x38, 0x71), RGB(0x00, 0x1C, 0x71),

    RGB(0x38, 0x38, 0x71), RGB(0x45, 0x38, 0x71), RGB(0x55, 0x38, 0x71), RGB(0x61, 0x38, 0x71),
    RGB(0x71, 0x38, 0x71), RGB(0x71, 0x38, 0x61), RGB(0x71, 0x38, 0x55), RGB(0x71, 0x38, 0x45),
    RGB(0x71, 0x38, 0x38), RGB(0x71, 0x45, 0x38), RGB(0x71, 0x55, 0x38), RGB(0x71, 0x61, 0x38),
    RGB(0x71, 0x71, 0x38), RGB(0x61, 0x71, 0x38), RGB(0x55, 0x71, 0x38), RGB(0x45, 0x71, 0x38),
    RGB(0x38, 0x71, 0x38), RGB(0x38, 0x71, 0x45), RGB(0x38, 0x71, 0x55), RGB(0x38, 0x71, 0x61),
    RGB(0x38, 0x71, 0x71), RGB(0x38, 0x61, 0x71), RGB(0x38, 0x55, 0x71), RGB(0x38, 0x45, 0x71),
    RGB(0x51, 0x51, 0x71), RGB(0x59, 0x51, 0x71), RGB(0x61, 0x51, 0x71), RGB(0x69, 0x51, 0x71),
    RGB(0x71, 0x51, 0x71), RGB(0x71, 0x51, 0x69), RGB(0x71, 0x51, 0x61), RGB(0x71, 0x51, 0x59),
    RGB(0x71, 0x51, 0x51), RGB(0x71, 0x59, 0x51), RGB(0x71, 0x61, 0x51), RGB(0x71, 0x69, 0x51),
    RGB(0x71, 0x71, 0x51), RGB(0x69, 0x71, 0x51), RGB(0x61, 0x71, 0x51), RGB(0x59, 0x71, 0x51),
    RGB(0x51, 0x71, 0x51), RGB(0x51, 0x71, 0x59), RGB(0x51, 0x71, 0x61), RGB(0x51, 0x71, 0x69),
    RGB(0x51, 0x71, 0x71), RGB(0x51, 0x69, 0x71), RGB(0x51, 0x61, 0x71), RGB(0x51, 0x59, 0x71),
    RGB(0x00, 0x00, 0x41), RGB(0x10, 0x00, 0x41), RGB(0x20, 0x00, 0x41), RGB(0x30, 0x00, 0x41),
    RGB(0x41, 0x00, 0x41), RGB(0x41, 0x00, 0x30), RGB(0x41, 0x00, 0x20), RGB(0x41, 0x00, 0x10),
    RGB(0x41, 0x00, 0x00), RGB(0x41, 0x10, 0x00), RGB(0x41, 0x20, 0x00), RGB(0x41, 0x30, 0x00),
    RGB(0x41, 0x41, 0x00), RGB(0x30, 0x41, 0x00), RGB(0x20, 0x41, 0x00), RGB(0x10, 0x41, 0x00),

    RGB(0x00, 0x41, 0x00), RGB(0x00, 0x41, 0x10), RGB(0x00, 0x41, 0x20), RGB(0x00, 0x41, 0x30),
    RGB(0x00, 0x41, 0x41), RGB(0x00, 0x30, 0x41), RGB(0x00, 0x20, 0x41), RGB(0x00, 0x10, 0x41),
    RGB(0x20, 0x20, 0x41), RGB(0x28, 0x20, 0x41), RGB(0x30, 0x20, 0x41), RGB(0x38, 0x20, 0x41),
    RGB(0x41, 0x20, 0x41), RGB(0x41, 0x20, 0x38), RGB(0x41, 0x20, 0x30), RGB(0x41, 0x20, 0x28),
    RGB(0x41, 0x20, 0x20), RGB(0x41, 0x28, 0x20), RGB(0x41, 0x30, 0x20), RGB(0x41, 0x38, 0x20),
    RGB(0x41, 0x41, 0x20), RGB(0x38, 0x41, 0x20), RGB(0x30, 0x41, 0x20), RGB(0x28, 0x41, 0x20),
    RGB(0x20, 0x41, 0x20), RGB(0x20, 0x41, 0x28), RGB(0x20, 0x41, 0x30), RGB(0x20, 0x41, 0x38),
    RGB(0x20, 0x41, 0x41), RGB(0x20, 0x38, 0x41), RGB(0x20, 0x30, 0x41), RGB(0x20, 0x28, 0x41),
    RGB(0x2C, 0x2C, 0x41), RGB(0x30, 0x2C, 0x41), RGB(0x34, 0x2C, 0x41), RGB(0x3C, 0x2C, 0x41),
    RGB(0x41, 0x2C, 0x41), RGB(0x41, 0x2C, 0x3C), RGB(0x41, 0x2C, 0x34), RGB(0x41, 0x2C, 0x30),
    RGB(0x41, 0x2C, 0x2C), RGB(0x41, 0x30, 0x2C), RGB(0x41, 0x34, 0x2C), RGB(0x41, 0x3C, 0x2C),
    RGB(0x41, 0x41, 0x2C), RGB(0x3C, 0x41, 0x2C), RGB(0x34, 0x41, 0x2C), RGB(0x30, 0x41, 0x2C),
    RGB(0x2C, 0x41, 0x2C), RGB(0x2C, 0x41, 0x30), RGB(0x2C, 0x41, 0x34), RGB(0x2C, 0x41, 0x3C),
    RGB(0x2C, 0x41, 0x41), RGB(0x2C, 0x3C, 0x41), RGB(0x2C, 0x34, 0x41), RGB(0x2C, 0x30, 0x41),
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00),
    RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00), RGB(0x00, 0x00, 0x00)
};

#endif

static CONST UCHAR Font8x8[VGA_FONT_CHARACTERS * 8] =
{
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x7E, 0x81, 0xA5, 0x81, 0xBD, 0x99, 0x81, 0x7E,
    0x7E, 0xFF, 0xDB, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E,
    0x6C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00,
    0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00,
    0x38, 0x7C, 0x38, 0xFE, 0xFE, 0x92, 0x10, 0x7C,
    0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x7C,
    0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00,
    0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF,
    0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00,
    0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF,
    0x0F, 0x07, 0x0F, 0x7D, 0xCC, 0xCC, 0xCC, 0x78,
    0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18,
    0x3F, 0x33, 0x3F, 0x30, 0x30, 0x70, 0xF0, 0xE0,
    0x7F, 0x63, 0x7F, 0x63, 0x63, 0x67, 0xE6, 0xC0,
    0x99, 0x5A, 0x3C, 0xE7, 0xE7, 0x3C, 0x5A, 0x99,
    0x80, 0xE0, 0xF8, 0xFE, 0xF8, 0xE0, 0x80, 0x00,
    0x02, 0x0E, 0x3E, 0xFE, 0x3E, 0x0E, 0x02, 0x00,
    0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18,
    0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00,
    0x7F, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x00,
    0x3E, 0x63, 0x38, 0x6C, 0x6C, 0x38, 0x86, 0xFC,
    0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x00,
    0x18, 0x3C, 0x7E, 0x18, 0x7E, 0x3C, 0x18, 0xFF,
    0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x00,
    0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00,
    0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00,
    0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00,
    0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00,
    0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00,
    0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x00, 0x00,
    0x00, 0xFF, 0xFF, 0x7E, 0x3C, 0x18, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00,
    0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0x00,
    0x18, 0x7E, 0xC0, 0x7C, 0x06, 0xFC, 0x18, 0x00,
    0x00, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xC6, 0x00,
    0x38, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0x76, 0x00,
    0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00,
    0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00,
    0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00,
    0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30,
    0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00,
    0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00,
    0x7C, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0x7C, 0x00,
    0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xFC, 0x00,
    0x78, 0xCC, 0x0C, 0x38, 0x60, 0xCC, 0xFC, 0x00,
    0x78, 0xCC, 0x0C, 0x38, 0x0C, 0xCC, 0x78, 0x00,
    0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x1E, 0x00,
    0xFC, 0xC0, 0xF8, 0x0C, 0x0C, 0xCC, 0x78, 0x00,
    0x38, 0x60, 0xC0, 0xF8, 0xCC, 0xCC, 0x78, 0x00,
    0xFC, 0xCC, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00,
    0x78, 0xCC, 0xCC, 0x78, 0xCC, 0xCC, 0x78, 0x00,
    0x78, 0xCC, 0xCC, 0x7C, 0x0C, 0x18, 0x70, 0x00,
    0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00,
    0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30,
    0x18, 0x30, 0x60, 0xC0, 0x60, 0x30, 0x18, 0x00,
    0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00,
    0x60, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x60, 0x00,
    0x3C, 0x66, 0x0C, 0x18, 0x18, 0x00, 0x18, 0x00,
    0x7C, 0xC6, 0xDE, 0xDE, 0xDC, 0xC0, 0x7C, 0x00,
    0x30, 0x78, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0x00,
    0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00,
    0x3C, 0x66, 0xC0, 0xC0, 0xC0, 0x66, 0x3C, 0x00,
    0xF8, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00,
    0xFE, 0x62, 0x68, 0x78, 0x68, 0x62, 0xFE, 0x00,
    0xFE, 0x62, 0x68, 0x78, 0x68, 0x60, 0xF0, 0x00,
    0x3C, 0x66, 0xC0, 0xC0, 0xCE, 0x66, 0x3A, 0x00,
    0xCC, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0xCC, 0x00,
    0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
    0x1E, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, 0x00,
    0xE6, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0xE6, 0x00,
    0xF0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00,
    0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0x00,
    0xC6, 0xE6, 0xF6, 0xDE, 0xCE, 0xC6, 0xC6, 0x00,
    0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00,
    0xFC, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00,
    0x7C, 0xC6, 0xC6, 0xC6, 0xD6, 0x7C, 0x0E, 0x00,
    0xFC, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0xE6, 0x00,
    0x7C, 0xC6, 0xE0, 0x78, 0x0E, 0xC6, 0x7C, 0x00,
    0xFC, 0xB4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
    0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xFC, 0x00,
    0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00,
    0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00,
    0xC6, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0xC6, 0x00,
    0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x30, 0x78, 0x00,
    0xFE, 0xC6, 0x8C, 0x18, 0x32, 0x66, 0xFE, 0x00,
    0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00,
    0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x02, 0x00,
    0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00,
    0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
    0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00,
    0xE0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xDC, 0x00,
    0x00, 0x00, 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x00,
    0x1C, 0x0C, 0x0C, 0x7C, 0xCC, 0xCC, 0x76, 0x00,
    0x00, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00,
    0x38, 0x6C, 0x64, 0xF0, 0x60, 0x60, 0xF0, 0x00,
    0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8,
    0xE0, 0x60, 0x6C, 0x76, 0x66, 0x66, 0xE6, 0x00,
    0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
    0x0C, 0x00, 0x1C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78,
    0xE0, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0xE6, 0x00,
    0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
    0x00, 0x00, 0xCC, 0xFE, 0xFE, 0xD6, 0xD6, 0x00,
    0x00, 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0xCC, 0x00,
    0x00, 0x00, 0x78, 0xCC, 0xCC, 0xCC, 0x78, 0x00,
    0x00, 0x00, 0xDC, 0x66, 0x66, 0x7C, 0x60, 0xF0,
    0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0x1E,
    0x00, 0x00, 0xDC, 0x76, 0x62, 0x60, 0xF0, 0x00,
    0x00, 0x00, 0x7C, 0xC0, 0x70, 0x1C, 0xF8, 0x00,
    0x10, 0x30, 0xFC, 0x30, 0x30, 0x34, 0x18, 0x00,
    0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00,
    0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00,
    0x00, 0x00, 0xC6, 0xC6, 0xD6, 0xFE, 0x6C, 0x00,
    0x00, 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00,
    0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8,
    0x00, 0x00, 0xFC, 0x98, 0x30, 0x64, 0xFC, 0x00,
    0x1C, 0x30, 0x30, 0xE0, 0x30, 0x30, 0x1C, 0x00,
    0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00,
    0xE0, 0x30, 0x30, 0x1C, 0x30, 0x30, 0xE0, 0x00,
    0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0x00,
    0x7C, 0xC6, 0xC0, 0xC6, 0x7C, 0x0C, 0x06, 0x7C,
    0x00, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00,
    0x1C, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00,
    0x7E, 0x81, 0x3C, 0x06, 0x3E, 0x66, 0x3B, 0x00,
    0xCC, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00,
    0xE0, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00,
    0x30, 0x30, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00,
    0x00, 0x00, 0x7C, 0xC6, 0xC0, 0x78, 0x0C, 0x38,
    0x7E, 0x81, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00,
    0xCC, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00,
    0xE0, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00,
    0xCC, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
    0x7C, 0x82, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00,
    0xE0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
    0xC6, 0x10, 0x7C, 0xC6, 0xFE, 0xC6, 0xC6, 0x00,
    0x30, 0x30, 0x00, 0x78, 0xCC, 0xFC, 0xCC, 0x00,
    0x1C, 0x00, 0xFC, 0x60, 0x78, 0x60, 0xFC, 0x00,
    0x00, 0x00, 0x7F, 0x0C, 0x7F, 0xCC, 0x7F, 0x00,
    0x3E, 0x6C, 0xCC, 0xFE, 0xCC, 0xCC, 0xCE, 0x00,
    0x78, 0x84, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00,
    0x00, 0xCC, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00,
    0x00, 0xE0, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00,
    0x78, 0x84, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00,
    0x00, 0xE0, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00,
    0x00, 0xCC, 0x00, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8,
    0xC3, 0x18, 0x3C, 0x66, 0x66, 0x3C, 0x18, 0x00,
    0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x00,
    0x18, 0x18, 0x7E, 0xC0, 0xC0, 0x7E, 0x18, 0x18,
    0x38, 0x6C, 0x64, 0xF0, 0x60, 0xE6, 0xFC, 0x00,
    0xCC, 0xCC, 0x78, 0x30, 0xFC, 0x30, 0xFC, 0x30,
    0xF8, 0xCC, 0xCC, 0xFA, 0xC6, 0xCF, 0xC6, 0xC3,
    0x0E, 0x1B, 0x18, 0x3C, 0x18, 0x18, 0xD8, 0x70,
    0x1C, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00,
    0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
    0x00, 0x1C, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00,
    0x00, 0x1C, 0x00, 0xCC, 0xCC, 0xCC, 0x76, 0x00,
    0x00, 0xF8, 0x00, 0xB8, 0xCC, 0xCC, 0xCC, 0x00,
    0xFC, 0x00, 0xCC, 0xEC, 0xFC, 0xDC, 0xCC, 0x00,
    0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00, 0x00,
    0x38, 0x6C, 0x6C, 0x38, 0x00, 0x7C, 0x00, 0x00,
    0x18, 0x00, 0x18, 0x18, 0x30, 0x66, 0x3C, 0x00,
    0x00, 0x00, 0x00, 0xFC, 0xC0, 0xC0, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xFC, 0x0C, 0x0C, 0x00, 0x00,
    0xC6, 0xCC, 0xD8, 0x36, 0x6B, 0xC2, 0x84, 0x0F,
    0xC3, 0xC6, 0xCC, 0xDB, 0x37, 0x6D, 0xCF, 0x03,
    0x18, 0x00, 0x18, 0x18, 0x3C, 0x3C, 0x18, 0x00,
    0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00,
    0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00,
    0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
    0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
    0xDB, 0xF6, 0xDB, 0x6F, 0xDB, 0x7E, 0xD7, 0xED,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0x18, 0x18,
    0x18, 0x18, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18,
    0x36, 0x36, 0x36, 0x36, 0xF6, 0x36, 0x36, 0x36,
    0x00, 0x00, 0x00, 0x00, 0xFE, 0x36, 0x36, 0x36,
    0x00, 0x00, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18,
    0x36, 0x36, 0xF6, 0x06, 0xF6, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x00, 0x00, 0xFE, 0x06, 0xF6, 0x36, 0x36, 0x36,
    0x36, 0x36, 0xF6, 0x06, 0xFE, 0x00, 0x00, 0x00,
    0x36, 0x36, 0x36, 0x36, 0xFE, 0x00, 0x00, 0x00,
    0x18, 0x18, 0xF8, 0x18, 0xF8, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, 0x00, 0x00,
    0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0xFF, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18,
    0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
    0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18,
    0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x37, 0x30, 0x3F, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x3F, 0x30, 0x37, 0x36, 0x36, 0x36,
    0x36, 0x36, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFF, 0x00, 0xF7, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36,
    0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00,
    0x36, 0x36, 0xF7, 0x00, 0xF7, 0x36, 0x36, 0x36,
    0x18, 0x18, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00,
    0x36, 0x36, 0x36, 0x36, 0xFF, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFF, 0x00, 0xFF, 0x18, 0x18, 0x18,
    0x00, 0x00, 0x00, 0x00, 0xFF, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x36, 0x36, 0x3F, 0x00, 0x00, 0x00,
    0x18, 0x18, 0x1F, 0x18, 0x1F, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18,
    0x00, 0x00, 0x00, 0x00, 0x3F, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x36, 0x36, 0xFF, 0x36, 0x36, 0x36,
    0x18, 0x18, 0xFF, 0x18, 0xFF, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0xF8, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x18, 0x18,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
    0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
    0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x76, 0xDC, 0xC8, 0xDC, 0x76, 0x00,
    0x00, 0x78, 0xCC, 0xF8, 0xCC, 0xF8, 0xC0, 0xC0,
    0x00, 0xFC, 0xCC, 0xC0, 0xC0, 0xC0, 0xC0, 0x00,
    0x00, 0x00, 0xFE, 0x6C, 0x6C, 0x6C, 0x6C, 0x00,
    0xFC, 0xCC, 0x60, 0x30, 0x60, 0xCC, 0xFC, 0x00,
    0x00, 0x00, 0x7E, 0xD8, 0xD8, 0xD8, 0x70, 0x00,
    0x00, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0xC0,
    0x00, 0x76, 0xDC, 0x18, 0x18, 0x18, 0x18, 0x00,
    0xFC, 0x30, 0x78, 0xCC, 0xCC, 0x78, 0x30, 0xFC,
    0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0x6C, 0x38, 0x00,
    0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x6C, 0xEE, 0x00,
    0x1C, 0x30, 0x18, 0x7C, 0xCC, 0xCC, 0x78, 0x00,
    0x00, 0x00, 0x7E, 0xDB, 0xDB, 0x7E, 0x00, 0x00,
    0x06, 0x0C, 0x7E, 0xDB, 0xDB, 0x7E, 0x60, 0xC0,
    0x38, 0x60, 0xC0, 0xF8, 0xC0, 0x60, 0x38, 0x00,
    0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x00,
    0x00, 0x7E, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00,
    0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x7E, 0x00,
    0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xFC, 0x00,
    0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xFC, 0x00,
    0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0xD8, 0x70,
    0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00,
    0x00, 0x76, 0xDC, 0x00, 0x76, 0xDC, 0x00, 0x00,
    0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
    0x0F, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x3C, 0x1C,
    0x58, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00,
    0x70, 0x98, 0x30, 0x60, 0xF8, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

static CONST UCHAR Font8x14[VGA_FONT_CHARACTERS * 14] =
{
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81,
    0x81, 0xBD, 0x99, 0x81, 0x7E, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x7E, 0xFF, 0xDB, 0xFF,
    0xFF, 0xC3, 0xE7, 0xFF, 0x7E, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE,
    0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7C,
    0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0xE7,
    0xE7, 0xE7, 0x18, 0x18, 0x3C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0xFF,
    0xFF, 0x7E, 0x18, 0x18, 0x3C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
    0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7,
    0xC3, 0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66,
    0x42, 0x42, 0x66, 0x3C, 0x00, 0x00, 0x00,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x99,
    0xBD, 0xBD, 0x99, 0xC3, 0xFF, 0xFF, 0xFF,
    0x00, 0x00, 0x00, 0x1E, 0x0E, 0x1A, 0x32,
    0x78, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66,
    0x3C, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x3F, 0x33, 0x3F, 0x30,
    0x30, 0x30, 0x70, 0xF0, 0xE0, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x7F, 0x63, 0x7F, 0x63,
    0x63, 0x63, 0x67, 0xE7, 0xE6, 0xC0, 0x00,
    0x00, 0x00, 0x00, 0x18, 0x18, 0xDB, 0x3C,
    0xE7, 0x3C, 0xDB, 0x18, 0x18, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF8,
    0xFE, 0xF8, 0xE0, 0xC0, 0x80, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x02, 0x06, 0x0E, 0x3E,
    0xFE, 0x3E, 0x0E, 0x06, 0x02, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18,
    0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66,
    0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x7F, 0xDB, 0xDB, 0xDB,
    0x7B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00,
    0x00, 0x7C, 0xC6, 0x60, 0x38, 0x6C, 0xC6,
    0x6C, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFE,
    0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18,
    0x18, 0x18, 0x7E, 0x3C, 0x18, 0x7E, 0x00,
    0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0C,
    0xFE, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60,
    0xFE, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0,
    0xC0, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6C,
    0xFE, 0x6C, 0x28, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38,
    0x7C, 0x7C, 0xFE, 0xFE, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x7C,
    0x7C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x3C,
    0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00,
    0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x6C, 0x6C, 0xFE, 0x6C,
    0x6C, 0x6C, 0xFE, 0x6C, 0x6C, 0x00, 0x00,
    0x00, 0x18, 0x18, 0x7C, 0xC6, 0xC2, 0xC0,
    0x7C, 0x06, 0x86, 0xC6, 0x7C, 0x18, 0x18,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0xC6,
    0x0C, 0x18, 0x30, 0x66, 0xC6, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x38, 0x6C, 0x6C, 0x38,
    0x76, 0xDC, 0xCC, 0xCC, 0x76, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x30,
    0x30, 0x30, 0x30, 0x18, 0x0C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x30, 0x18, 0x0C, 0x0C,
    0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3C,
    0xFF, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
    0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x02, 0x06, 0x0C, 0x18,
    0x30, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6,
    0xD6, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x0C,
    0x18, 0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06,
    0x3C, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x0C, 0x1C, 0x3C, 0x6C,
    0xCC, 0xFE, 0x0C, 0x0C, 0x1E, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xFE, 0xC0, 0xC0, 0xC0,
    0xFC, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x38, 0x60, 0xC0, 0xC0,
    0xFC, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xFE, 0xC6, 0x06, 0x0C,
    0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6,
    0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6,
    0x7E, 0x06, 0x06, 0x0C, 0x78, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
    0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
    0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00,
    0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x60,
    0xC0, 0x60, 0x30, 0x18, 0x0C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E,
    0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0C,
    0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x0C,
    0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xDE,
    0xDE, 0xDE, 0xDC, 0xC0, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6,
    0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66,
    0x7C, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0,
    0xC0, 0xC0, 0xC2, 0x66, 0x3C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xF8, 0x6C, 0x66, 0x66,
    0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68,
    0x78, 0x68, 0x62, 0x66, 0xFE, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68,
    0x78, 0x68, 0x60, 0x60, 0xF0, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0,
    0xC0, 0xDE, 0xC6, 0x66, 0x3A, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6,
    0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x3C, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1E, 0x0C, 0x0C, 0x0C,
    0x0C, 0x0C, 0xCC, 0xCC, 0x78, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xE6, 0x66, 0x6C, 0x6C,
    0x78, 0x6C, 0x6C, 0x66, 0xE6, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xF0, 0x60, 0x60, 0x60,
    0x60, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xD6,
    0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xC6, 0xE6, 0xF6, 0xFE,
    0xDE, 0xCE, 0xC6, 0xC6, 0xC6, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6,
    0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66,
    0x7C, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6,
    0xC6, 0xC6, 0xD6, 0xDE, 0x7C, 0x0E, 0x00,
    0x00, 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66,
    0x7C, 0x6C, 0x66, 0x66, 0xE6, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x60,
    0x38, 0x0C, 0xC6, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x7E, 0x7E, 0x5A, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6,
    0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6,
    0xC6, 0xC6, 0x6C, 0x38, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6,
    0xD6, 0xD6, 0xFE, 0x6C, 0x6C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0x7C,
    0x38, 0x7C, 0xC6, 0xC6, 0xC6, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66,
    0x3C, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xFE, 0xC6, 0x8C, 0x18,
    0x30, 0x60, 0xC2, 0xC6, 0xFE, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x3C, 0x30, 0x30, 0x30,
    0x30, 0x30, 0x30, 0x30, 0x3C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x70,
    0x38, 0x1C, 0x0E, 0x06, 0x02, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C,
    0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00, 0x00,
    0x38, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00,
    0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,
    0x0C, 0x7C, 0xCC, 0xCC, 0x76, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xE0, 0x60, 0x60, 0x78,
    0x6C, 0x66, 0x66, 0x66, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C,
    0xC6, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1C, 0x0C, 0x0C, 0x3C,
    0x6C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C,
    0xC6, 0xFE, 0xC0, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1C, 0x36, 0x32, 0x30,
    0x7C, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76,
    0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0x78,
    0x00, 0x00, 0x00, 0xE0, 0x60, 0x60, 0x6C,
    0x76, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x38,
    0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0E,
    0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C,
    0x00, 0x00, 0x00, 0xE0, 0x60, 0x60, 0x66,
    0x6C, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC,
    0xFE, 0xD6, 0xD6, 0xD6, 0xD6, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC,
    0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C,
    0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC,
    0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0xF0,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76,
    0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0x1E,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC,
    0x76, 0x66, 0x60, 0x60, 0xF0, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C,
    0xC6, 0x70, 0x1C, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x10, 0x30, 0x30, 0xFC,
    0x30, 0x30, 0x30, 0x36, 0x1C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC,
    0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6,
    0xC6, 0xC6, 0x6C, 0x38, 0x10, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6,
    0xC6, 0xD6, 0xD6, 0xFE, 0x6C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6,
    0x6C, 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6,
    0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x7C,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
    0xCC, 0x18, 0x30, 0x66, 0xFE, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x0E, 0x18, 0x18, 0x18,
    0x70, 0x18, 0x18, 0x18, 0x0E, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x70, 0x18, 0x18, 0x18,
    0x0E, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00,
    0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
    0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0,
    0xC0, 0xC0, 0xC2, 0x66, 0x3C, 0x18, 0x70,
    0x00, 0x00, 0x00, 0x00, 0xCC, 0x00, 0xCC,
    0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00,
    0x00, 0x00, 0x06, 0x0C, 0x18, 0x00, 0x7C,
    0xC6, 0xFE, 0xC0, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x10, 0x38, 0x6C, 0x00, 0x78,
    0x0C, 0x7C, 0xCC, 0xCC, 0x76, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0xCC, 0x00, 0x78,
    0x0C, 0x7C, 0xCC, 0xCC, 0x76, 0x00, 0x00,
    0x00, 0x00, 0xC0, 0x60, 0x30, 0x00, 0x78,
    0x0C, 0x7C, 0xCC, 0xCC, 0x76, 0x00, 0x00,
    0x00, 0x00, 0x38, 0x6C, 0x38, 0x00, 0x78,
    0x0C, 0x7C, 0xCC, 0xCC, 0x76, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C,
    0xC6, 0xC0, 0xC0, 0xC6, 0x7C, 0x18, 0x70,
    0x00, 0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C,
    0xC6, 0xFE, 0xC0, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x7C,
    0xC6, 0xFE, 0xC0, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x7C,
    0xC6, 0xFE, 0xC0, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x38,
    0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00,
    0x00, 0x00, 0x18, 0x3C, 0x66, 0x00, 0x38,
    0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00,
    0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x38,
    0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00,
    0x00, 0xC6, 0x00, 0x10, 0x38, 0x6C, 0xC6,
    0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00,
    0x38, 0x6C, 0x38, 0x10, 0x38, 0x6C, 0xC6,
    0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00,
    0x0C, 0x18, 0x00, 0xFE, 0x66, 0x62, 0x68,
    0x78, 0x68, 0x62, 0x66, 0xFE, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC,
    0x36, 0x76, 0xDC, 0xD8, 0x6E, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x3E, 0x6C, 0xCC, 0xCC,
    0xFE, 0xCC, 0xCC, 0xCC, 0xCE, 0x00, 0x00,
    0x00, 0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C,
    0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x7C,
    0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x7C,
    0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x30, 0x78, 0xCC, 0x00, 0xCC,
    0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00,
    0x00, 0x00, 0xC0, 0x60, 0x30, 0x00, 0xCC,
    0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0xC6, 0x00, 0xC6,
    0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x7C,
    0x00, 0xC6, 0x00, 0x7C, 0xC6, 0xC6, 0xC6,
    0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0xC6, 0x00, 0xC6, 0xC6, 0xC6, 0xC6,
    0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x18, 0x18, 0x7C, 0xC6,
    0xC0, 0xC6, 0x7C, 0x18, 0x18, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x38, 0x6C, 0x64, 0x60,
    0xF0, 0x60, 0x60, 0x66, 0xFC, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x66, 0x66, 0x3C, 0x18,
    0x7E, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xFC, 0x66, 0x66, 0x7C,
    0x62, 0x66, 0x6F, 0x66, 0xF3, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x0E, 0x1B, 0x18, 0x18,
    0x7E, 0x18, 0x18, 0xD8, 0x70, 0x00, 0x00,
    0x00, 0x00, 0x0C, 0x18, 0x30, 0x00, 0x78,
    0x0C, 0x7C, 0xCC, 0xCC, 0x76, 0x00, 0x00,
    0x00, 0x00, 0x06, 0x0C, 0x18, 0x00, 0x38,
    0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00,
    0x00, 0x00, 0x06, 0x0C, 0x18, 0x00, 0x7C,
    0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x0C, 0x18, 0x30, 0x00, 0xCC,
    0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x76, 0xDC, 0x00, 0xDC,
    0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00,
    0x76, 0xDC, 0x00, 0xC6, 0xE6, 0xF6, 0xFE,
    0xDE, 0xCE, 0xC6, 0xC6, 0xC6, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x3C, 0x6C, 0x6C, 0x36,
    0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x38, 0x6C, 0x6C, 0x38,
    0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x30,
    0x30, 0x60, 0xC6, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
    0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
    0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x60, 0xE0, 0x63, 0x66, 0x6C, 0x18,
    0x30, 0x6E, 0xC3, 0x06, 0x0C, 0x1F, 0x00,
    0x00, 0x60, 0xE0, 0x63, 0x66, 0x6C, 0x18,
    0x36, 0x6E, 0xDA, 0x3F, 0x06, 0x06, 0x00,
    0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18,
    0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x36, 0x6C, 0xD8, 0x6C, 0x36, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xD8, 0x6C, 0x36, 0x6C, 0xD8, 0x00, 0x00,
    0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11,
    0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
    0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55,
    0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
    0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD,
    0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18,
    0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xFE, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18,
    0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06,
    0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06,
    0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06,
    0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18,
    0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18,
    0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30,
    0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x30,
    0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00,
    0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00,
    0xF7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30,
    0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00,
    0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00,
    0xF7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00,
    0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00,
    0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18,
    0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18,
    0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x3F, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0xFF, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18,
    0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
    0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
    0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
    0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76,
    0xDC, 0xD8, 0xD8, 0xDC, 0x76, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x78, 0xCC, 0xCC, 0xD8,
    0xCC, 0xC6, 0xC6, 0xC6, 0xCC, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC0,
    0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
    0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xFE, 0xC6, 0x60, 0x30,
    0x18, 0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E,
    0xD8, 0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66,
    0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0xC0,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76,
    0xDC, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x7E, 0x18, 0x3C, 0x66,
    0x66, 0x66, 0x3C, 0x18, 0x7E, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6,
    0xFE, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6,
    0xC6, 0x6C, 0x6C, 0x6C, 0xEE, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1E, 0x30, 0x18, 0x0C,
    0x3E, 0x66, 0x66, 0x66, 0x3C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xDB,
    0xDB, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x03, 0x06, 0x7E, 0xDB,
    0xDB, 0xF3, 0x7E, 0x60, 0xC0, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1E, 0x30, 0x60, 0x60,
    0x7E, 0x60, 0x60, 0x30, 0x1E, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6,
    0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00,
    0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18,
    0x18, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x30, 0x18, 0x0C, 0x06,
    0x0C, 0x18, 0x30, 0x00, 0x7E, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x60,
    0x30, 0x18, 0x0C, 0x00, 0x7E, 0x00, 0x00,
    0x00, 0x00, 0x0E, 0x1B, 0x1B, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00,
    0x7E, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC,
    0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x38, 0x6C, 0x6C, 0x38,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x0F, 0x0C, 0x0C, 0x0C, 0x0C,
    0x0C, 0xEC, 0x6C, 0x3C, 0x1C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x6C, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x3C, 0x66, 0x0C, 0x18,
    0x32, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E,
    0x7E, 0x7E, 0x7E, 0x7E, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

static CONST UCHAR Font8x16[VGA_FONT_CHARACTERS * 16] =
{
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xBD,
    0x99, 0x81, 0x81, 0x7E, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x7C, 0xFE, 0xFE, 0xD6, 0xFE, 0xFE,
    0xBA, 0xC6, 0xFE, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x6C, 0xEE, 0xFE, 0xFE, 0xFE,
    0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C,
    0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x10, 0x6C,
    0xEE, 0x6C, 0x10, 0x38, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x10, 0x38, 0x7C, 0x7C, 0xFE, 0xFE,
    0xFE, 0x6C, 0x10, 0x38, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C,
    0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC3, 0xC3,
    0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x66, 0x66,
    0x66, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC3, 0x99, 0x99,
    0x99, 0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0x00, 0x00, 0x1E, 0x0E, 0x1E, 0x36, 0x78, 0xCC,
    0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18,
    0x7E, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x1E, 0x1A, 0x1E, 0x18, 0x18, 0x18,
    0x18, 0x78, 0xF8, 0x70, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x3E, 0x36, 0x3E, 0x36, 0x36, 0x76,
    0xF6, 0x66, 0x0E, 0x1E, 0x0C, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x18, 0xDB, 0x7E, 0x3C, 0x66, 0x66,
    0x3C, 0x7E, 0xDB, 0x18, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xFC, 0xFE,
    0xFC, 0xF0, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x02, 0x0E, 0x3E, 0x7E, 0xFE,
    0x7E, 0x3E, 0x0E, 0x02, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18,
    0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
    0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x7F, 0xDB, 0xDB, 0xDB, 0xDB, 0x7B,
    0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x60, 0x7C, 0xF6,
    0xDE, 0x7C, 0x0C, 0xC6, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xFE, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18,
    0x7E, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0E, 0xFF,
    0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x70, 0xFE,
    0x70, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0,
    0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xFF,
    0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x38, 0x7C,
    0x7C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xFE, 0xFE, 0x7C, 0x7C, 0x7C,
    0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x3C, 0x18,
    0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x36, 0x36, 0x36, 0x36, 0x14, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x6C, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C,
    0xFE, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x18, 0x18, 0x7C, 0xC6, 0xC0, 0x78,
    0x3C, 0x06, 0xC6, 0x7C, 0x18, 0x18, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x66, 0x0C,
    0x18, 0x30, 0x66, 0xC6, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x38, 0x6C, 0x38, 0x30, 0x76, 0x7E,
    0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x0C, 0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30,
    0x30, 0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x0C,
    0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x38, 0xFE,
    0x38, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E,
    0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x0C, 0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0C, 0x18,
    0x30, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6,
    0xE6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x18, 0x78, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x06, 0x0C, 0x18,
    0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06,
    0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x0C, 0x1C, 0x3C, 0x6C, 0xCC, 0xCC,
    0xFE, 0x0C, 0x0C, 0x1E, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFE, 0xC0, 0xC0, 0xC0, 0xFC, 0x06,
    0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0xFC, 0xC6,
    0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFE, 0xC6, 0x06, 0x0C, 0x18, 0x30,
    0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6,
    0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E,
    0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00,
    0x00, 0x0C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00,
    0x00, 0x0C, 0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x60, 0xC0,
    0x60, 0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00,
    0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0C, 0x06,
    0x0C, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x0C, 0x18, 0x18,
    0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xDE, 0xDE,
    0xDE, 0xDC, 0xC0, 0x7E, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xFE,
    0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66,
    0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0,
    0xC0, 0xC2, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x66,
    0x66, 0x66, 0x6C, 0xF8, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFE, 0x66, 0x60, 0x64, 0x7C, 0x64,
    0x60, 0x60, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFE, 0x66, 0x60, 0x64, 0x7C, 0x64,
    0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0,
    0xCE, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6,
    0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xC6, 0xC6, 0xCC, 0xD8, 0xF0, 0xF0,
    0xD8, 0xCC, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x60, 0x60,
    0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xC6, 0xC6, 0xEE, 0xEE, 0xFE, 0xD6,
    0xD6, 0xD6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xC6, 0xC6, 0xE6, 0xE6, 0xF6, 0xDE,
    0xCE, 0xCE, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
    0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x66, 0x7C,
    0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
    0xC6, 0xD6, 0xD6, 0x7C, 0x06, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x78,
    0x6C, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0x70, 0x1C,
    0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
    0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
    0xC6, 0x6C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6, 0xD6,
    0xFE, 0xEE, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x38,
    0x6C, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C,
    0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFE, 0xC6, 0x86, 0x0C, 0x18, 0x30,
    0x60, 0xC2, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x7C, 0x60, 0x60, 0x60, 0x60, 0x60,
    0x60, 0x60, 0x60, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, 0x30,
    0x18, 0x0C, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x7C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
    0x0C, 0x0C, 0x0C, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00,
    0x00, 0x18, 0x18, 0x18, 0x0C, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C,
    0xCC, 0xCC, 0xDC, 0x76, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xE0, 0x60, 0x60, 0x7C, 0x66, 0x66,
    0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0,
    0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x1C, 0x0C, 0x0C, 0x7C, 0xCC, 0xCC,
    0xCC, 0xCC, 0xCC, 0x7E, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6,
    0xFE, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x1C, 0x36, 0x30, 0x30, 0xFC, 0x30,
    0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCE, 0xC6,
    0xC6, 0xCE, 0x76, 0x06, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0xE0, 0x60, 0x60, 0x7C, 0x66, 0x66,
    0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x0C, 0x0C, 0x00, 0x1C, 0x0C, 0x0C,
    0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, 0x00, 0x00,
    0x00, 0x00, 0xE0, 0x60, 0x60, 0x66, 0x66, 0x6C,
    0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x1C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xD6,
    0xD6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66,
    0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6,
    0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66,
    0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC,
    0xCC, 0xCC, 0x7C, 0x0C, 0x0C, 0x1E, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x60,
    0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0,
    0x7C, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x30, 0x30, 0x30, 0xFC, 0x30, 0x30,
    0x30, 0x30, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC,
    0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6,
    0xC6, 0x6C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xD6,
    0xD6, 0xD6, 0xFE, 0x6C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0x6C,
    0x38, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6,
    0xC6, 0xCE, 0x76, 0x06, 0xC6, 0x7C, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x86, 0x0C,
    0x18, 0x30, 0x62, 0xFE, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x0E, 0x18, 0x18, 0x18, 0x70, 0x18,
    0x18, 0x18, 0x18, 0x0E, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0E, 0x18,
    0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38,
    0x6C, 0x6C, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x3C, 0x66, 0xC0, 0xC0, 0xC0, 0xC6,
    0x66, 0x3C, 0x18, 0x0C, 0xCC, 0x38, 0x00, 0x00,
    0x00, 0x00, 0xC6, 0x00, 0x00, 0xC6, 0xC6, 0xC6,
    0xC6, 0xC6, 0xCE, 0x76, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x0C, 0x18, 0x30, 0x00, 0x7C, 0xC6, 0xC6,
    0xFE, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x30, 0x78, 0xCC, 0x00, 0x78, 0x0C, 0x7C,
    0xCC, 0xCC, 0xDC, 0x76, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xCC, 0x00, 0x00, 0x78, 0x0C, 0x7C,
    0xCC, 0xCC, 0xDC, 0x76, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0C, 0x7C,
    0xCC, 0xCC, 0xDC, 0x76, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x38, 0x6C, 0x38, 0x00, 0x78, 0x0C, 0x7C,
    0xCC, 0xCC, 0xDC, 0x76, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0,
    0xC6, 0x7C, 0x18, 0x0C, 0x6C, 0x38, 0x00, 0x00,
    0x00, 0x30, 0x78, 0xCC, 0x00, 0x7C, 0xC6, 0xC6,
    0xFE, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xCC, 0x00, 0x00, 0x7C, 0xC6, 0xC6,
    0xFE, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x30, 0x18, 0x0C, 0x00, 0x7C, 0xC6, 0xC6,
    0xFE, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x18, 0x3C, 0x66, 0x00, 0x38, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0xC6, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6,
    0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
    0x38, 0x6C, 0x38, 0x00, 0x38, 0x6C, 0xC6, 0xC6,
    0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
    0x0C, 0x18, 0x30, 0x00, 0xFE, 0x60, 0x60, 0x7C,
    0x60, 0x60, 0x60, 0xFE, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x66, 0xDB, 0x1B, 0x7F,
    0xD8, 0xD8, 0xDF, 0x76, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x7E, 0xD8, 0xD8, 0xD8, 0xD8, 0xFE,
    0xD8, 0xD8, 0xD8, 0xDE, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x30, 0x78, 0xCC, 0x00, 0x7C, 0xC6, 0xC6,
    0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xC6, 0x00, 0x00, 0x7C, 0xC6, 0xC6,
    0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x30, 0x18, 0x0C, 0x00, 0x7C, 0xC6, 0xC6,
    0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x30, 0x78, 0xCC, 0x00, 0xC6, 0xC6, 0xC6,
    0xC6, 0xC6, 0xCE, 0x76, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x60, 0x30, 0x18, 0x00, 0xC6, 0xC6, 0xC6,
    0xC6, 0xC6, 0xCE, 0x76, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x18, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0xC6, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6,
    0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0xC6, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
    0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x18, 0x18, 0x7C, 0xC6, 0xC0, 0xC0,
    0xC6, 0x7C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x38, 0x6C, 0x60, 0x60, 0xF0, 0x60, 0x60,
    0x60, 0x66, 0xF6, 0x6C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E,
    0x18, 0x3C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x3E, 0x63, 0x63, 0x30, 0x1C, 0x06,
    0x63, 0x63, 0x3E, 0x00, 0x1C, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x63, 0x38,
    0x0E, 0x63, 0x3E, 0x00, 0x1C, 0x00, 0x00, 0x00,
    0x00, 0x0C, 0x18, 0x30, 0x00, 0x78, 0x0C, 0x7C,
    0xCC, 0xCC, 0xDC, 0x76, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x0C, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x0C, 0x18, 0x30, 0x00, 0x7C, 0xC6, 0xC6,
    0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x18, 0x30, 0x60, 0x00, 0xCC, 0xCC, 0xCC,
    0xCC, 0xCC, 0xDC, 0x76, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x76, 0xDC, 0x00, 0xBC, 0x66, 0x66,
    0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x76, 0xDC, 0x00, 0xC6, 0xC6, 0xE6, 0xF6,
    0xDE, 0xCE, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x21, 0x1E, 0x00, 0x1E, 0x33, 0x60, 0x60,
    0x67, 0x63, 0x33, 0x1D, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x42, 0x3C, 0x00, 0x3B, 0x66, 0x66, 0x66,
    0x3E, 0x06, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x30,
    0x60, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E,
    0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E,
    0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x60, 0x60, 0x62, 0x66, 0x6C, 0x18, 0x30,
    0x60, 0xDC, 0x36, 0x0C, 0x18, 0x3E, 0x00, 0x00,
    0x00, 0x60, 0x60, 0x62, 0x66, 0x6C, 0x18, 0x36,
    0x6E, 0xDE, 0x36, 0x7E, 0x06, 0x06, 0x00, 0x00,
    0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x3C,
    0x3C, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6C, 0xD8,
    0x6C, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x6C, 0x36,
    0x6C, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
    0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
    0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55,
    0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55,
    0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77,
    0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xF6,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0xF8,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06, 0xF6,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06, 0xF6,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06, 0xFE,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFE,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3F,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x30, 0x37,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xFF,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xF7,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xF7,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0xFF,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3F,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x1F,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF,
    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
    0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0xFF,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
    0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
    0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
    0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0xD8, 0xD8,
    0xD8, 0xD8, 0xDC, 0x76, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x78, 0xCC, 0xCC, 0xD8, 0xFC, 0xC6,
    0xC6, 0xC6, 0xC6, 0xCC, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFE, 0x66, 0x62, 0x60, 0x60, 0x60,
    0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x6C, 0x6C,
    0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFE, 0xC6, 0x62, 0x30, 0x18, 0x18,
    0x30, 0x62, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xD8, 0xCC,
    0xCC, 0xCC, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66,
    0x66, 0x7C, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFE, 0x38, 0x38, 0x6C, 0xC6, 0xC6,
    0x6C, 0x38, 0x38, 0xFE, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xFE,
    0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xC6,
    0x6C, 0x6C, 0x6C, 0xEE, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x3E, 0x60, 0x60, 0x3C, 0x66, 0xC6,
    0xC6, 0xC6, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xDB, 0xDB,
    0xDB, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x02, 0x06, 0x7C, 0xCE, 0xDE, 0xF6,
    0xF6, 0x7C, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1C, 0x30, 0x60, 0x60, 0x7C,
    0x60, 0x60, 0x30, 0x1C, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
    0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE,
    0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18,
    0x18, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18,
    0x30, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18,
    0x0C, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x0C, 0x1E, 0x1A, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
    0x18, 0x18, 0x58, 0x78, 0x30, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7E,
    0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC,
    0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
    0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18,
    0xD8, 0xD8, 0x78, 0x38, 0x18, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xD8, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x70, 0xD8, 0x18, 0x30, 0x60, 0xF8,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E,
    0x7E, 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};


/*
 * Table of supported Video Modes.
 *
 * See http://wiki.osdev.org/Drawing_In_Protected_Mode#Locating_Video_Memory
 * Values of PageSize taken from DOSBox.
 */

typedef struct _VGA_MODE
{
    PVGA_REGISTERS VgaRegisters;
    WORD PageSize;
    WORD CharacterWidth;
    WORD CharacterHeight;
    // PCOLORREF Palette;
} VGA_MODE, *PVGA_MODE;

static CONST VGA_MODE VideoModes[BIOS_MAX_VIDEO_MODE + 1] =
{
    {&VideoMode_40x25_text,         0x0800, 9, 16},    /* Mode 00h - 16 color (mono)                       */
    {&VideoMode_40x25_text,         0x0800, 9, 16},    /* Mode 01h - 16 color                              */
    {&VideoMode_80x25_text,         0x1000, 9, 16},    /* Mode 02h - 16 color (mono)                       */
    {&VideoMode_80x25_text,         0x1000, 9, 16},    /* Mode 03h - 16 color                              */
    {&VideoMode_320x200_4color,     0x4000, 8,  8},    /* Mode 04h - CGA 4 color                           */
    {&VideoMode_320x200_4color,     0x4000, 8,  8},    /* Mode 05h - CGA same (m) (uses 3rd CGA palette)   */
    {&VideoMode_640x200_2color,     0x4000, 8,  8},    /* Mode 06h - CGA 640*200 2 color                   */
    {NULL,                          0x1000, 1,  1},    /* Mode 07h - MDA monochrome text 80*25             */
    {NULL,                          0x0000, 1,  1},    /* Mode 08h - PCjr                                  */
    {NULL,                          0x0000, 1,  1},    /* Mode 09h - PCjr                                  */
    {NULL,                          0x0000, 1,  1},    /* Mode 0Ah - PCjr                                  */
    {NULL,                          0x0000, 1,  1},    /* Mode 0Bh - Reserved                              */
    {NULL,                          0x0000, 1,  1},    /* Mode 0Ch - Reserved                              */
    {&VideoMode_320x200_16color,    0x2000, 8,  8},    /* Mode 0Dh - EGA 320*200 16 color                  */
    {&VideoMode_640x200_16color,    0x4000, 8,  8},    /* Mode 0Eh - EGA 640*200 16 color                  */
    {NULL,                          0x8000, 1,  1},    /* Mode 0Fh - EGA 640*350 mono                      */
    {&VideoMode_640x350_16color,    0x8000, 8, 14},    /* Mode 10h - EGA 640*350 HiRes 16 color            */
    {&VideoMode_640x480_2color,     0xA000, 8, 16},    /* Mode 11h - VGA 640*480 mono                      */
    {&VideoMode_640x480_16color,    0xA000, 8, 16},    /* Mode 12h - VGA                                   */
    {&VideoMode_320x200_256color,   0x2000, 8,  8},    /* Mode 13h - VGA                                   */
};

#define IS_TEXT_MODE(ModeNumber)    \
    (((ModeNumber) >= 0x00 && (ModeNumber) <= 0x03) || ((ModeNumber) == 0x07))

static PVGA_STATIC_FUNC_TABLE VgaStaticFuncTable;
static BOOLEAN VbeInitialized = FALSE;

/* PRIVATE FUNCTIONS **********************************************************/

static BOOLEAN VidBiosScrollWindow(SCROLL_DIRECTION Direction,
                                   DWORD Amount,
                                   SMALL_RECT Rectangle,
                                   BYTE Page,
                                   BYTE FillAttribute)
{
    INT i, j;
    DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Page * Bda->VideoPageSize);
    WORD FillCharacter = MAKEWORD(' ', FillAttribute);

    WORD WindowWidth, WindowHeight;

    /* TODO: This function doesn't work in non-alphanumeric modes yet */
    if (Bda->VideoMode > 3)
    {
        DPRINT1("VidBiosScrollWindow: not implemented for mode 0%Xh\n", Bda->VideoMode);
        return FALSE;
    }

    /* Fixup the rectangle if needed */
    Rectangle.Left   = min(max(Rectangle.Left  , 0), Bda->ScreenColumns - 1);
    Rectangle.Right  = min(max(Rectangle.Right , 0), Bda->ScreenColumns - 1);
    Rectangle.Top    = min(max(Rectangle.Top   , 0), Bda->ScreenRows);
    Rectangle.Bottom = min(max(Rectangle.Bottom, 0), Bda->ScreenRows);

    WindowWidth  = Rectangle.Right  - Rectangle.Left + 1;
    WindowHeight = Rectangle.Bottom - Rectangle.Top  + 1;

    /* Amount == 0 means we clear all the rectangle */
    if ((Amount == 0) ||
        (((Direction == SCROLL_UP  ) || (Direction == SCROLL_DOWN )) && (Amount >= WindowHeight)) ||
        (((Direction == SCROLL_LEFT) || (Direction == SCROLL_RIGHT)) && (Amount >= WindowWidth )))
    {
        /* Fill the rectangle */
        for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
        {
            for (j = Rectangle.Left; j <= Rectangle.Right; j++)
            {
                EmulatorWriteMemory(&EmulatorContext,
                                    VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
                                    (LPVOID)&FillCharacter,
                                    sizeof(FillCharacter));
            }
        }

        return TRUE;
    }

    switch (Direction)
    {
        case SCROLL_UP:
        {
            /* Move text lines up */
            for (i = Rectangle.Top + Amount; i <= Rectangle.Bottom; i++)
            {
                EmulatorCopyMemory(&EmulatorContext,
                                   VideoAddress + ((i - Amount) * Bda->ScreenColumns + Rectangle.Left) * sizeof(WORD),
                                   VideoAddress + ( i           * Bda->ScreenColumns + Rectangle.Left) * sizeof(WORD),
                                   (Rectangle.Right - Rectangle.Left + 1) * sizeof(WORD));
            }

            /* Fill the bottom of the rectangle */
            for (i = Rectangle.Bottom - Amount + 1; i <= Rectangle.Bottom; i++)
            {
                for (j = Rectangle.Left; j <= Rectangle.Right; j++)
                {
                    EmulatorWriteMemory(&EmulatorContext,
                                        VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
                                        (LPVOID)&FillCharacter,
                                        sizeof(FillCharacter));
                }
            }

            break;
        }

        case SCROLL_DOWN:
        {
            INT Bottom;

            /* Move text lines down */
            for (i = Rectangle.Bottom - Amount; i >= Rectangle.Top; i--)
            {
                EmulatorCopyMemory(&EmulatorContext,
                                   VideoAddress + ((i + Amount) * Bda->ScreenColumns + Rectangle.Left) * sizeof(WORD),
                                   VideoAddress + ( i           * Bda->ScreenColumns + Rectangle.Left) * sizeof(WORD),
                                   (Rectangle.Right - Rectangle.Left + 1) * sizeof(WORD));
            }

            /* Fill the top of the rectangle */
            Bottom = Rectangle.Top + Amount - 1;
            for (i = Rectangle.Top; i <= Bottom; i++)
            {
                for (j = Rectangle.Left; j <= Rectangle.Right; j++)
                {
                    EmulatorWriteMemory(&EmulatorContext,
                                        VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
                                        (LPVOID)&FillCharacter,
                                        sizeof(FillCharacter));
                }
            }

            break;
        }

        case SCROLL_LEFT:
        {
            /* Move text lines left */
            for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
            {
                EmulatorCopyMemory(&EmulatorContext,
                                   VideoAddress + (i * Bda->ScreenColumns + Rectangle.Left         ) * sizeof(WORD),
                                   VideoAddress + (i * Bda->ScreenColumns + Rectangle.Left + Amount) * sizeof(WORD),
                                   (Rectangle.Right - Rectangle.Left - Amount + 1) * sizeof(WORD));
            }

            /* Fill the right of the rectangle */
            for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
            {
                for (j = Rectangle.Right - Amount + 1; j <= Rectangle.Right; j++)
                {
                    EmulatorWriteMemory(&EmulatorContext,
                                        VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
                                        (LPVOID)&FillCharacter,
                                        sizeof(FillCharacter));
                }
            }

            break;
        }

        case SCROLL_RIGHT:
        {
            INT Right;

            /* Move text lines right */
            for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
            {
                EmulatorCopyMemory(&EmulatorContext,
                                   VideoAddress + (i * Bda->ScreenColumns + Rectangle.Left + Amount) * sizeof(WORD),
                                   VideoAddress + (i * Bda->ScreenColumns + Rectangle.Left         ) * sizeof(WORD),
                                   (Rectangle.Right - Rectangle.Left - Amount + 1) * sizeof(WORD));
            }

            /* Fill the left of the rectangle */
            Right = Rectangle.Left + Amount - 1;
            for (i = Rectangle.Top; i <= Rectangle.Bottom; i++)
            {
                for (j = Rectangle.Left; j <= Right; j++)
                {
                    EmulatorWriteMemory(&EmulatorContext,
                                        VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD),
                                        (LPVOID)&FillCharacter,
                                        sizeof(FillCharacter));
                }
            }

            break;
        }
    }

    return TRUE;
}

static __inline VOID VgaSetSinglePaletteRegister(BYTE Index, BYTE Value)
{
    /* Write the index */
    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
    IOWriteB(VGA_AC_INDEX, Index);

    /* Write the data */
    IOWriteB(VGA_AC_WRITE, Value);
}

static BOOLEAN VgaSetRegisters(PVGA_REGISTERS Registers)
{
    UINT i;

    if (Registers == NULL) return FALSE;

    /* Disable interrupts */
    setIF(0);

    /*
     * Set the CRT base address according to the selected mode,
     * monochrome or color. The following macros:
     * VGA_INSTAT1_READ, VGA_CRTC_INDEX and VGA_CRTC_DATA are then
     * used to access the correct VGA I/O ports.
     */
    Bda->CrtBasePort = (Registers->Misc & 0x01) ? VGA_CRTC_INDEX_COLOR
                                                : VGA_CRTC_INDEX_MONO;
    /* Bit 1 indicates whether display is color (0) or monochrome (1) */
    Bda->VGAOptions     = (Bda->VGAOptions     & 0xFD) | (!(Registers->Misc & 0x01) << 1);
    Bda->CrtModeControl = (Bda->CrtModeControl & 0xFB) | (!(Registers->Misc & 0x01) << 1);

    /* Update blink bit in BDA */
    if (Registers->Attribute[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_BLINK)
        Bda->CrtModeControl |= (1 << 5);
    else
        Bda->CrtModeControl &= ~(1 << 5);

    /* Turn the video off */
    IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_CLOCK_REG);
    IOWriteB(VGA_SEQ_DATA , IOReadB(VGA_SEQ_DATA) | VGA_SEQ_CLOCK_SD);

    /* Write the misc register */
    IOWriteB(VGA_MISC_WRITE, Registers->Misc);

    /* Synchronous reset on */
    IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_RESET_REG);
    IOWriteB(VGA_SEQ_DATA , VGA_SEQ_RESET_AR );

    /* Write the sequencer registers */
    for (i = 1; i < VGA_SEQ_MAX_REG; i++)
    {
        IOWriteB(VGA_SEQ_INDEX, i);
        IOWriteB(VGA_SEQ_DATA , Registers->Sequencer[i]);
    }

    /* Synchronous reset off */
    IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_RESET_REG);
    IOWriteB(VGA_SEQ_DATA , VGA_SEQ_RESET_SR | VGA_SEQ_RESET_AR);

    /* Unlock CRTC registers 0-7 */
    IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_END_HORZ_BLANKING_REG);
    IOWriteB(VGA_CRTC_DATA , IOReadB(VGA_CRTC_DATA) | 0x80);
    IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_END_VERT_RETRACE_REG);
    IOWriteB(VGA_CRTC_DATA , IOReadB(VGA_CRTC_DATA) & ~0x80);
    // Make sure they remain unlocked
    Registers->CRT[VGA_CRTC_END_HORZ_BLANKING_REG] |= 0x80;
    Registers->CRT[VGA_CRTC_END_VERT_RETRACE_REG] &= ~0x80;

    /* Write the CRTC registers */
    for (i = 0; i < VGA_CRTC_MAX_REG; i++)
    {
        IOWriteB(VGA_CRTC_INDEX, i);
        IOWriteB(VGA_CRTC_DATA , Registers->CRT[i]);
    }

    /* Write the GC registers */
    for (i = 0; i < VGA_GC_MAX_REG; i++)
    {
        IOWriteB(VGA_GC_INDEX, i);
        IOWriteB(VGA_GC_DATA , Registers->Graphics[i]);
    }

    /* Write the AC registers */
    for (i = 0; i < VGA_AC_MAX_REG; i++)
    {
        VgaSetSinglePaletteRegister(i, Registers->Attribute[i]);
    }

    /* Set the PEL mask */
    IOWriteB(VGA_DAC_MASK, 0xFF);

    /* Enable screen and disable palette access */
    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
    IOWriteB(VGA_AC_INDEX, 0x20);

    /* Turn the video on */
    IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_CLOCK_REG);
    IOWriteB(VGA_SEQ_DATA , IOReadB(VGA_SEQ_DATA) & ~VGA_SEQ_CLOCK_SD);

    /* Enable interrupts */
    setIF(1);

    return TRUE;
}

static VOID VgaSetPalette(const COLORREF* Palette, ULONG Size)
{
    ULONG i;

    // /* Disable screen and enable palette access */
    // IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
    // IOWriteB(VGA_AC_INDEX, 0x00);

    for (i = 0; i < Size; i++)
    {
        IOWriteB(VGA_DAC_WRITE_INDEX, i);
        IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetRValue(Palette[i])));
        IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetGValue(Palette[i])));
        IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(GetBValue(Palette[i])));
    }

    /* The following step might be optional */
    for (i = Size; i < VGA_MAX_COLORS; i++)
    {
        IOWriteB(VGA_DAC_WRITE_INDEX, i);
        IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(0x00));
        IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(0x00));
        IOWriteB(VGA_DAC_DATA, VGA_COLOR_TO_DAC(0x00));
    }

    /* Enable screen and disable palette access */
    // IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
    // IOWriteB(VGA_AC_INDEX, 0x20);
}

static VOID VgaChangePalette(BYTE ModeNumber)
{
    const COLORREF* Palette;
    ULONG Size;

    if (ModeNumber >= 0x13)
    {
        /* VGA modes */
        Palette = VgaPalette;
        Size    = ARRAYSIZE(VgaPalette);
    }
    else if (ModeNumber == 0x10) // || (ModeNumber == 0x0D) || (ModeNumber == 0x0E)
    {
        /* EGA HiRes mode */
        Palette = EgaPalette__HiRes;
        Size    = ARRAYSIZE(EgaPalette__HiRes);
    }
#if 0
    else if ((ModeNumber == 0x04) || (ModeNumber == 0x05))
    {
        /*
         * CGA modes; this palette contains both normal and
         * bright versions of CGA palettes 0 and 1
         */
        Palette = CgaPalette2;
        Size    = ARRAYSIZE(CgaPalette2);
    }
#endif
    else // if ((ModeNumber == 0x0D) || (ModeNumber == 0x0E))
    {
        /* EGA modes */
        Palette = EgaPalette__16Colors;
        Size    = ARRAYSIZE(EgaPalette__16Colors);
    }

    VgaSetPalette(Palette, Size);
}

static __inline VOID VidBiosGetCursorPosition(PBYTE Row, PBYTE Column, BYTE Page)
{
    *Row    = HIBYTE(Bda->CursorPosition[Page]);
    *Column = LOBYTE(Bda->CursorPosition[Page]);
}

static VOID VidBiosSetCursorPosition(BYTE Row, BYTE Column, BYTE Page)
{
    /* Update the position in the BDA */
    Bda->CursorPosition[Page] = MAKEWORD(Column, Row);

    /* Check if this is the current video page */
    if (Page == Bda->VideoPage)
    {
        WORD Offset = Row * Bda->ScreenColumns + Column;

        /* Modify the CRTC registers */
        IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_LOW_REG);
        IOWriteB(VGA_CRTC_DATA , LOBYTE(Offset));
        IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_HIGH_REG);
        IOWriteB(VGA_CRTC_DATA , HIBYTE(Offset));
    }
}

static VOID VidBiosSetCursorShape(WORD CursorStartEnd)
{
    /* Only valid in text-mode */
    if (!IS_TEXT_MODE(Bda->VideoMode)) return;

    /* Update the BDA */
    Bda->CursorStartLine = HIBYTE(CursorStartEnd) & 0x1F;
    Bda->CursorEndLine   = LOBYTE(CursorStartEnd) & 0x1F;

    /*
     * In cursor emulation mode, we suppose the cursor scanlines
     * to be in CGA mode, so that we need to adjust them
     *
     * WARNING!!
     * =========
     * Contrary to what is mentioned in lots of literature out there, e.g. in:
     * http://webpages.charter.net/danrollins/techhelp/0072.HTM
     * http://www.bioscentral.com/misc/bda.htm
     * and in other various places, bit 0 of Bda->VGAOptions is 0 when
     * cursor emulation is ENABLED, and is 1 when it is DISABLED.
     *
     * The following documentation is right about this fact:
     * http://www.cs.nyu.edu/~mwalfish/classes/ut/s12-cs372h/ref/hardware/vgadoc/VGABIOS.TXT
     * https://sites.google.com/site/pcdosretro/biosdata
     *
     * A proof that it is OK is that in the following code samples it is
     * explicitly mentioned that setting bit 0 disables cursor emulation:
     * - Code snippets in PC Magazine vol.5 num.15 of 16/09/1986, p.291-292;
     * - CardFile DOS utility (Jeff Prosise, PC Magazine vol.6 num.17 of 13/10/1987, p.403-416):
     *   https://ia600700.us.archive.org/1/items/srccode-00000020/cardfile.asm.txt
     *   (function 'show_cursor', "or ega_info,1    ;disable EGA cursor emulation")
     */
    if (!(Bda->VGAOptions & 0x01))
    {
        // HACK: Quick "fix" for cursor scanline adjustment. This must be reworked.
        DPRINT1("HACK: Using HACK for cursor scanlines adjustment\n");
        CursorStartEnd = MAKEWORD((LOBYTE(CursorStartEnd) & 0x1F) * 2,
                                  (HIBYTE(CursorStartEnd) & 0x1F) * 2 | (HIBYTE(CursorStartEnd) & 0xE0));
    }

    /* Modify the CRTC registers */
    IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_START_REG);
    IOWriteB(VGA_CRTC_DATA , HIBYTE(CursorStartEnd));
    IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_END_REG);
    IOWriteB(VGA_CRTC_DATA , LOBYTE(CursorStartEnd));
}

static VOID VidBiosSyncCursorPosition(VOID)
{
    BYTE Row, Column;
    BYTE Low, High;
    SHORT ScreenColumns = Bda->ScreenColumns;
    WORD Offset;

    /* Get the cursor position */
    IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_LOW_REG);
    Low  = IOReadB(VGA_CRTC_DATA);
    IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_HIGH_REG);
    High = IOReadB(VGA_CRTC_DATA);

    Offset = MAKEWORD(Low, High);

    Row    = (BYTE)(Offset / ScreenColumns);
    Column = (BYTE)(Offset % ScreenColumns);

    /* Synchronize our cursor position with VGA */
    VidBiosSetCursorPosition(Row, Column, Bda->VideoPage);
}

static inline BYTE VidBiosGetVideoMode(VOID)
{
    /* Bit 7 of VideoMode is determined by bit 7 of VGAOptions */
    return Bda->VideoMode | (Bda->VGAOptions & 0x80);
}

static inline VOID VidBiosClearScreen(VOID)
{
    static const DWORD MemoryMaps[4]  = { 0xA0000, 0xA0000, 0xB0000, 0xB8000 };
    static const DWORD MemorySizes[4] = { 0x20000, 0x10000, 0x08000, 0x08000 };

    DWORD VideoAddress;
    DWORD BufferSize;
    BYTE Misc;
    BYTE Buffer[0x20000];

    /* Read the misc register */
    IOWriteB(VGA_GC_INDEX, VGA_GC_MISC_REG);
    Misc = IOReadB(VGA_GC_DATA);

    /* Get the video address and buffer size */
    VideoAddress = MemoryMaps[(Misc >> 2) & 3];
    BufferSize  = MemorySizes[(Misc >> 2) & 3];

    // !IS_TEXT_MODE(Bda->VideoMode)
    if (Misc & 1)
    {
        /* Graphics mode */
        RtlZeroMemory(Buffer, BufferSize);
    }
    else
    {
        /* Text mode */
        UINT i;
        for (i = 0; i < (BufferSize >> 1); i++)
        {
            ((PWORD)Buffer)[i] = MAKEWORD(' ', DEFAULT_ATTRIBUTE);
        }
    }

    /* Write to video memory */
    EmulatorWriteMemory(&EmulatorContext, VideoAddress, Buffer, BufferSize);
}

static BOOLEAN VidBiosSetVideoMode(BYTE ModeNumber)
{
    BYTE Page;
    COORD Resolution;
    BYTE OrgModeNumber = ModeNumber;

    /*
     * IBM standard modes do not clear the screen if the
     * high bit of AL is set (EGA or higher only).
     * See Ralf Brown: http://www.ctyme.com/intr/rb-0069.htm
     * for more information.
     */
    BOOLEAN DoNotClear = !!(ModeNumber & 0x80);

    /* Retrieve the real mode number and check its validity */
    ModeNumber &= 0x7F;
    // if (ModeNumber >= ARRAYSIZE(VideoModes))

    DPRINT1("Switching to mode %02Xh (%02Xh) %s clearing the screen; VgaRegisters = 0x%p\n",
            ModeNumber, OrgModeNumber, (DoNotClear ? "without" : "and"), VideoModes[ModeNumber].VgaRegisters);

    if (ModeNumber > BIOS_MAX_VIDEO_MODE)
    {
        /* This could be an extended video mode, so call the VBE BIOS */
        return VbeSetExtendedVideoMode(ModeNumber);
    }

    if (!VgaSetRegisters(VideoModes[ModeNumber].VgaRegisters)) return FALSE;
    if (VbeInitialized && Bda->VideoMode > BIOS_MAX_VIDEO_MODE)
    {
        /*
         * Since we're switching from an extended video mode to a standard VGA
         * mode, tell the VBE BIOS to reset the extended registers.
         */
        VbeResetExtendedRegisters();
    }

    VgaChangePalette(ModeNumber);

    /* Clear the VGA memory if needed */
    if (!DoNotClear) VgaClearMemory();

    /* Update the values in the BDA */
    Bda->VideoMode       = ModeNumber;
    Bda->VideoPageSize   = VideoModes[ModeNumber].PageSize;
    Bda->VideoPage       = 0;
    Bda->VideoPageOffset = Bda->VideoPage * Bda->VideoPageSize;

    /* 256 KB Video RAM; set bit 7 if we do not clear the screen */
    Bda->VGAOptions      = 0x60 | (Bda->VGAOptions & 0x7F) | (DoNotClear ? 0x80 : 0x00);
    Bda->VGASwitches     = 0xF9;    /* High-resolution  */

    // Bda->VGAFlags;
    // Bda->CrtModeControl;
    // Bda->CrtColorPaletteMask;

    /* Set the start address in the CRTC */
    IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_LOW_REG);
    IOWriteB(VGA_CRTC_DATA , LOBYTE(Bda->VideoPageOffset));
    IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_HIGH_REG);
    IOWriteB(VGA_CRTC_DATA , HIBYTE(Bda->VideoPageOffset));

    /* Update the screen size */
    Resolution = VgaGetDisplayResolution();
    // This could be simplified if the VGA helper always returned the resolution
    // in number of pixels, instead of in number of cells for text-modes only...
    if (!IS_TEXT_MODE(ModeNumber))
    {
        Resolution.X /= VideoModes[ModeNumber].CharacterWidth ;
        Resolution.Y /= VideoModes[ModeNumber].CharacterHeight;
    }
    Bda->ScreenColumns = Resolution.X;
    Bda->ScreenRows    = Resolution.Y - 1;

    /* Update the current font */
    Bda->CharacterHeight = VideoModes[ModeNumber].CharacterHeight;
    switch (Bda->CharacterHeight)
    {
        /*
         * Write the default font to the VGA font plane for text-modes only.
         * Update the BIOS INT 43h vector (far pointer to the character range 00h-...).
         */
        case 8:
        {
            if (IS_TEXT_MODE(ModeNumber))
                VgaWriteTextModeFont(0, Font8x8, ARRAYSIZE(Font8x8) / VGA_FONT_CHARACTERS);

            ((PULONG)BaseAddress)[0x43] = MAKELONG(FONT_8x8_OFFSET, VIDEO_BIOS_DATA_SEG);
            break;
        }
        case 14:
        {
            if (IS_TEXT_MODE(ModeNumber))
                VgaWriteTextModeFont(0, Font8x14, ARRAYSIZE(Font8x14) / VGA_FONT_CHARACTERS);

            ((PULONG)BaseAddress)[0x43] = MAKELONG(FONT_8x14_OFFSET, VIDEO_BIOS_DATA_SEG);
            break;
        }
        case 16:
        {
            if (IS_TEXT_MODE(ModeNumber))
                VgaWriteTextModeFont(0, Font8x16, ARRAYSIZE(Font8x16) / VGA_FONT_CHARACTERS);

            ((PULONG)BaseAddress)[0x43] = MAKELONG(FONT_8x16_OFFSET, VIDEO_BIOS_DATA_SEG);
            break;
        }
    }

#if 0 // Commented, because I need to think about how to change correctly the ScreenRows
      // in the code that really use it (the Font generator functions of INT 10h, AH=11h)
      // so that it also changes the screen resolution *in text mode only*.
    switch (getBL())
    {
        case 0x00: Bda->ScreenRows = getDL()-1; break;
        case 0x01: Bda->ScreenRows = 13;        break;
        case 0x03: Bda->ScreenRows = 42;        break;
        case 0x02:
        default  : Bda->ScreenRows = 24;        break;
    }
#endif

    /*
     * Update the cursor shape (text-mode only).
     * Use the default CGA cursor scanline values,
     * see: http://vitaly_filatov.tripod.com/ng/asm/asm_023.2.html
     */
    if (IS_TEXT_MODE(ModeNumber))
        // FIXME: we might read the CRT registers and do the adjustment?
        VidBiosSetCursorShape(MAKEWORD(0x07, 0x06));

    /* Set the cursor position for each page */
    for (Page = 0; Page < BIOS_MAX_PAGES; ++Page)
        VidBiosSetCursorPosition(0, 0, Page);

    if (!DoNotClear) VidBiosClearScreen();

    /* Refresh display */
    VgaRefreshDisplay();

    return TRUE;
}

static BOOLEAN VidBiosSetVideoPage(BYTE PageNumber)
{
    BYTE Row, Column;

    /* Check if the page exists */
    if (PageNumber >= BIOS_MAX_PAGES) return FALSE;

    /* Check if this is the same page */
    if (PageNumber == Bda->VideoPage) return TRUE;

    /* Update the values in the BDA */
    Bda->VideoPage       = PageNumber;
    Bda->VideoPageOffset = Bda->VideoPage * Bda->VideoPageSize;

    /* Set the start address in the CRTC */
    IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_LOW_REG);
    IOWriteB(VGA_CRTC_DATA , LOBYTE(Bda->VideoPageOffset));
    IOWriteB(VGA_CRTC_INDEX, VGA_CRTC_START_ADDR_HIGH_REG);
    IOWriteB(VGA_CRTC_DATA , HIBYTE(Bda->VideoPageOffset));

    /*
     * Get the cursor position (we don't update anything on the BIOS side
     * but we update the cursor position on the VGA side).
     */
    VidBiosGetCursorPosition(&Row, &Column, PageNumber);
    VidBiosSetCursorPosition( Row,  Column, PageNumber);

    return TRUE;
}

static VOID VidBiosDrawGlyph(WORD CharData, BOOLEAN UseAttr, BYTE Page, BYTE Row, BYTE Column)
{
    switch (Bda->VideoMode)
    {
        /* Alphanumeric mode */
        case 0x00:
        case 0x01:
        case 0x02:
        case 0x03:
        case 0x07:
        {
            EmulatorWriteMemory(&EmulatorContext,
                                TO_LINEAR(TEXT_VIDEO_SEG,
                                    Page * Bda->VideoPageSize +
                                    (Row * Bda->ScreenColumns + Column) * sizeof(WORD)),
                                (LPVOID)&CharData,
                                UseAttr ? sizeof(WORD) : sizeof(BYTE));
            break;
        }

        /* 4-color CGA */
        case 0x04:
        case 0x05:
        {
            WORD i;
            WORD CgaSegment[] = { CGA_EVEN_VIDEO_SEG, CGA_ODD_VIDEO_SEG };
            PUCHAR Font = (PUCHAR)FAR_POINTER(((PULONG)BaseAddress)[0x43]);
            PUCHAR Glyph = &Font[LOBYTE(CharData) * Bda->CharacterHeight];
            BOOLEAN Xor = (HIBYTE(CharData) & 0x80) ? TRUE : FALSE;
            BYTE OldRotate;
            BYTE DoubledBits[] =
            {
                0x00, 0x03, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F,
                0xC0, 0xC3, 0xCC, 0xCF, 0xF0, 0xF3, 0xFC, 0xFF
            };

            if (Xor)
            {
                /* Set the logical operation to XOR */
                IOWriteB(VGA_GC_INDEX, VGA_GC_ROTATE_REG);
                OldRotate = IOReadB(VGA_GC_DATA);
                IOWriteB(VGA_GC_DATA, OldRotate | 0x18);
            }

            for (i = 0; i < Bda->CharacterHeight; i++)
            {
                WORD Pixel = MAKEWORD(DoubledBits[Glyph[i] >> 4],
                                      DoubledBits[Glyph[i] & 0x0F]);
                if (Xor)
                {
                    USHORT Dummy;

                    /* Read from VGA memory to load the latch register */
                    EmulatorReadMemory(&EmulatorContext,
                                       TO_LINEAR(CgaSegment[(Row * Bda->CharacterHeight + i) & 1],
                                                 (((Row * Bda->CharacterHeight + i) >> 1)
                                                 * Bda->ScreenColumns + Column) * 2),
                                       (LPVOID)&Dummy,
                                       sizeof(USHORT));
                }

                EmulatorWriteMemory(&EmulatorContext,
                                    TO_LINEAR(CgaSegment[(Row * Bda->CharacterHeight + i) & 1],
                                              (((Row * Bda->CharacterHeight + i) >> 1)
                                              * Bda->ScreenColumns + Column) * 2),
                                    (LPVOID)&Pixel,
                                    sizeof(USHORT));
            }

            if (Xor)
            {
                IOWriteB(VGA_GC_INDEX, VGA_GC_ROTATE_REG);
                IOWriteB(VGA_GC_DATA, OldRotate);
            }

            break;
        }

        /* 2-color CGA */
        case 0x06:
        {
            WORD i;
            WORD CgaSegment[] = { CGA_EVEN_VIDEO_SEG, CGA_ODD_VIDEO_SEG };
            PUCHAR Font = (PUCHAR)FAR_POINTER(((PULONG)BaseAddress)[0x43]);
            PUCHAR Glyph = &Font[LOBYTE(CharData) * Bda->CharacterHeight];
            BOOLEAN Xor = (HIBYTE(CharData) & 0x80) ? TRUE : FALSE;
            BYTE OldRotate;

            if (Xor)
            {
                /* Set the logical operation to XOR */
                IOWriteB(VGA_GC_INDEX, VGA_GC_ROTATE_REG);
                OldRotate = IOReadB(VGA_GC_DATA);
                IOWriteB(VGA_GC_DATA, OldRotate | 0x18);
            }

            for (i = 0; i < Bda->CharacterHeight; i++)
            {
                if (Xor)
                {
                    UCHAR Dummy;

                    /* Read from VGA memory to load the latch register */
                    EmulatorReadMemory(&EmulatorContext,
                                       TO_LINEAR(CgaSegment[(Row * Bda->CharacterHeight + i) & 1],
                                                 (((Row * Bda->CharacterHeight + i) >> 1)
                                                 * Bda->ScreenColumns) + Column),
                                       (LPVOID)&Dummy,
                                       sizeof(UCHAR));
                }

                EmulatorWriteMemory(&EmulatorContext,
                                    TO_LINEAR(CgaSegment[(Row * Bda->CharacterHeight + i) & 1],
                                              (((Row * Bda->CharacterHeight + i) >> 1)
                                              * Bda->ScreenColumns) + Column),
                                    (LPVOID)&Glyph[i],
                                    sizeof(UCHAR));
            }

            if (Xor)
            {
                IOWriteB(VGA_GC_INDEX, VGA_GC_ROTATE_REG);
                IOWriteB(VGA_GC_DATA, OldRotate);
            }

            break;
        }

        /* 16-color modes */
        case 0x0D:
        case 0x0E:
        case 0x10:
        case 0x11:
        case 0x12:
        {
            WORD i;
            PUCHAR Font = (PUCHAR)FAR_POINTER(((PULONG)BaseAddress)[0x43]);
            PUCHAR Glyph = &Font[LOBYTE(CharData) * Bda->CharacterHeight];
            BOOLEAN Xor = (HIBYTE(CharData) & 0x80) ? TRUE : FALSE;
            BYTE OldPlaneWrite, OldReset, OldEnableReset, OldRotate, OldMode;

            /* Write to all planes */
            IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_MASK_REG);
            OldPlaneWrite = IOReadB(VGA_SEQ_DATA);
            IOWriteB(VGA_SEQ_DATA, 0x0F);

            /* Zero the planes whose bits are set in the enable set/reset register */
            IOWriteB(VGA_GC_INDEX, VGA_GC_RESET_REG);
            OldReset = IOReadB(VGA_GC_DATA);
            IOWriteB(VGA_GC_DATA, 0x00);

            /* Set the enable set/reset register to the inverse of the color */
            IOWriteB(VGA_GC_INDEX, VGA_GC_ENABLE_RESET_REG);
            OldEnableReset = IOReadB(VGA_GC_DATA);
            IOWriteB(VGA_GC_DATA, (~HIBYTE(CharData)) & 0x0F);

            /* Make sure we're in write mode 0 */
            IOWriteB(VGA_GC_INDEX, VGA_GC_MODE_REG);
            OldMode = IOReadB(VGA_GC_DATA);
            IOWriteB(VGA_GC_DATA, 0x00);

            if (Xor)
            {
                /* Set the logical operation to XOR */
                IOWriteB(VGA_GC_INDEX, VGA_GC_ROTATE_REG);
                OldRotate = IOReadB(VGA_GC_DATA);
                IOWriteB(VGA_GC_DATA, OldRotate | 0x18);
            }

            for (i = 0; i < Bda->CharacterHeight; i++)
            {
                if (Xor)
                {
                    UCHAR Dummy;

                    /* Read from VGA memory to load the latch register */
                    EmulatorReadMemory(&EmulatorContext,
                                       TO_LINEAR(GRAPHICS_VIDEO_SEG,
                                                 ((Row * Bda->CharacterHeight + i)
                                                 * Bda->ScreenColumns) + Column),
                                       (LPVOID)&Dummy,
                                       sizeof(UCHAR));
                }

                EmulatorWriteMemory(&EmulatorContext,
                                    TO_LINEAR(GRAPHICS_VIDEO_SEG,
                                              ((Row * Bda->CharacterHeight + i)
                                              * Bda->ScreenColumns) + Column),
                                    (LPVOID)&Glyph[i],
                                    sizeof(UCHAR));
            }

            /* Restore the registers */
            IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_MASK_REG);
            IOWriteB(VGA_SEQ_DATA, OldPlaneWrite);
            IOWriteB(VGA_GC_INDEX, VGA_GC_RESET_REG);
            IOWriteB(VGA_GC_DATA, OldReset);
            IOWriteB(VGA_GC_INDEX, VGA_GC_ENABLE_RESET_REG);
            IOWriteB(VGA_GC_DATA, OldEnableReset);
            IOWriteB(VGA_GC_INDEX, VGA_GC_MODE_REG);
            IOWriteB(VGA_GC_DATA, OldMode);

            if (Xor)
            {
                IOWriteB(VGA_GC_INDEX, VGA_GC_ROTATE_REG);
                IOWriteB(VGA_GC_DATA, OldRotate);
            }

            break;
        }

        /* 256-color mode */
        case 0x13:
        {
            WORD i, j;
            PUCHAR Font = (PUCHAR)FAR_POINTER(((PULONG)BaseAddress)[0x43]);
            PUCHAR Glyph = &Font[LOBYTE(CharData) * Bda->CharacterHeight];
            BYTE PixelBuffer[8]; // 8 == CharacterWidth

            for (i = 0; i < Bda->CharacterHeight; i++)
            {
                for (j = 0; j < ARRAYSIZE(PixelBuffer); j++)
                {
                    PixelBuffer[j] = (Glyph[i] & (1 << (7 - j))) ? HIBYTE(CharData) : 0;
                }

                EmulatorWriteMemory(&EmulatorContext,
                                    TO_LINEAR(GRAPHICS_VIDEO_SEG,
                                              ((Row * Bda->CharacterHeight + i)
                                              * Bda->ScreenColumns + Column) * 8),
                                    (LPVOID)PixelBuffer,
                                    sizeof(PixelBuffer));
            }

            break;
        }

        default:
        {
            DPRINT1("Drawing glyphs in mode %02Xh is not supported.\n", Bda->VideoMode);
        }
    }
}

static VOID VidBiosPrintCharacter(CHAR Character, BYTE Attribute, BOOLEAN UseAttr, BYTE Page)
{
    WORD CharData = MAKEWORD(Character, Attribute);
    BYTE Row, Column;

    /* Get the cursor position */
    VidBiosGetCursorPosition(&Row, &Column, Page);

    if (Character == '\a')
    {
        /* Bell control character */
        // NOTE: We may use what the terminal emulator offers to us...
        Beep(800, 200);
        return;
    }
    else if (Character == '\b')
    {
        /* Backspace control character */
        if (Column > 0)
        {
            Column--;
        }
        else if (Row > 0)
        {
            Column = Bda->ScreenColumns - 1;
            Row--;
        }

        /* Erase the existing character */
        CharData = MAKEWORD(' ', Attribute);
        VidBiosDrawGlyph(CharData, UseAttr, Page, Row, Column);
    }
    else if (Character == '\t')
    {
        /* Horizontal Tabulation control character */
        do
        {
            // Taken from DOSBox
            VidBiosPrintCharacter(' ', Attribute, UseAttr, Page);
            VidBiosGetCursorPosition(&Row, &Column, Page);
        } while (Column % 8);
    }
    else if (Character == '\n')
    {
        /* Line Feed control character */
        Row++;
    }
    else if (Character == '\r')
    {
        /* Carriage Return control character */
        Column = 0;
    }
    else
    {
        /* Default character */

        /* Write the character and advance the cursor */
        VidBiosDrawGlyph(CharData, UseAttr, Page, Row, Column);
        Column++;
    }

    /* Check if it passed the end of the row */
    if (Column >= Bda->ScreenColumns)
    {
        /* Return to the first column and go to the next line */
        Column = 0;
        Row++;
    }

    /* Scroll the screen up if needed */
    if (Row > Bda->ScreenRows)
    {
        /* The screen must be scrolled up */
        SMALL_RECT Rectangle = { 0, 0, Bda->ScreenColumns - 1, Bda->ScreenRows };
        VidBiosScrollWindow(SCROLL_UP, 1, Rectangle, Page, DEFAULT_ATTRIBUTE/*Attribute*/);
        Row--;
    }

    /* Set the cursor position */
    VidBiosSetCursorPosition(Row, Column, Page);
}

/* PUBLIC FUNCTIONS ***********************************************************/

VOID WINAPI VidBiosVideoService(LPWORD Stack)
{
    switch (getAH())
    {
        /* Set Video Mode */
        case 0x00:
        {
            VidBiosSetVideoMode(getAL());
            break;
        }

        /* Set Text-Mode Cursor Shape */
        case 0x01:
        {
            VidBiosSetCursorShape(getCX());
            break;
        }

        /* Set Cursor Position */
        case 0x02:
        {
            BYTE Page = getBH();

            /* Validate the selected video page */
            if (Page >= BIOS_MAX_PAGES) break;

            VidBiosSetCursorPosition(getDH(), getDL(), Page);
            break;
        }

        /* Get Cursor Position and Shape */
        case 0x03:
        {
            BYTE Page = getBH();

            /* Validate the selected video page */
            if (Page == 0xFF) // Special case: use the current video page
                Page = Bda->VideoPage;
            else if (Page >= BIOS_MAX_PAGES)
                break;

            /* Return the result */
            setCX(MAKEWORD(Bda->CursorEndLine, Bda->CursorStartLine));
            setDX(Bda->CursorPosition[Page]);
            break;
        }

        /* Query Light Pen */
        case 0x04:
        {
            /*
             * On modern BIOSes, this function returns 0
             * so that we can ignore the other registers.
             */
            setAX(0);
            break;
        }

        /* Select Active Display Page */
        case 0x05:
        {
            VidBiosSetVideoPage(getAL());
            break;
        }

        /* Scroll Window Up/Down */
        case 0x06:
        case 0x07:
        {
            SMALL_RECT Rectangle = { getCL(), getCH(), getDL(), getDH() };

            VidBiosScrollWindow((getAH() == 0x06) ? SCROLL_UP : SCROLL_DOWN,
                                getAL(), Rectangle, Bda->VideoPage, getBH());

            break;
        }

        /* Read Character and Attribute at Cursor Position */
        case 0x08:
        {
            WORD  CharData;
            BYTE  Page = getBH();
            DWORD Offset;

            /* Validate the selected video page */
            if (Page == 0xFF) // Special case: use the current video page
                Page = Bda->VideoPage;
            else if (Page >= BIOS_MAX_PAGES)
                break;

            /* Find the offset of the character */
            Offset = Page * Bda->VideoPageSize +
                     (HIBYTE(Bda->CursorPosition[Page])  * Bda->ScreenColumns +
                      LOBYTE(Bda->CursorPosition[Page])) * 2;

            /* Read from the video memory */
            EmulatorReadMemory(&EmulatorContext,
                               TO_LINEAR(TEXT_VIDEO_SEG, Offset),
                               (LPVOID)&CharData,
                               sizeof(WORD));

            /* Return the character data in AX */
            setAX(CharData);

            break;
        }

        /* Write Character and Attribute at Cursor Position */
        case 0x09:
        /* Write Character only (PCjr: + Attribute) at Cursor Position */
        case 0x0A:
        {
            WORD Counter = getCX();
            WORD CharData = MAKEWORD(getAL(), getBL());
            BOOLEAN UseAttr = (getAH() == 0x09);
            BYTE Page = getBH();
            BYTE Row, Column;

            /* Validate the selected video page */
            if (Page == 0xFF) // Special case: use the current video page
                Page = Bda->VideoPage;
            else if (Page >= BIOS_MAX_PAGES)
                break;

            /* Get the cursor position */
            VidBiosGetCursorPosition(&Row, &Column, Page);

            /* Write to video memory a certain number of times */
            while (Counter-- > 0)
            {
                /* Write the character and advance the position */
                VidBiosDrawGlyph(CharData, UseAttr, Page, Row, Column);
                Column++;

                /* Check if it passed the end of the row */
                if (Column >= Bda->ScreenColumns)
                {
                    /* Return to the first column and go to the next line */
                    Column = 0;
                    Row++;
                }

                /* Contrary to the "Teletype Output" function, the screen is not scrolled */
                if (Row > Bda->ScreenRows)
                {
                    Row = Bda->ScreenRows;
                }
            }

            break;
        }

        /* Set Video Colors */
        case 0x0B:
        {
            if (Bda->VideoMode < 0x04 || Bda->VideoMode > 0x06)
            {
                DPRINT1("BIOS Function INT 10h, AH = 0Bh, BH = 0x%02X is unsupported for non-CGA modes\n",
                        getBH());
                break;
            }

            switch (getBH())
            {
                case 0x00: /* Set Background/Border Color */
                {
#ifdef DOSBOX
                    BYTE Index = getBL();

                    /* See: http://www.bioscentral.com/misc/bda.htm */
                    Bda->CrtColorPaletteMask = (Bda->CrtColorPaletteMask & 0xE0) | (Index & 0x1F);

                    Index = ((Index << 1) & 0x10) | (Index & 0x7);

                    /* Always set the overscan color */
                    VgaSetSinglePaletteRegister(VGA_AC_OVERSCAN_REG, Index);

                    /* Don't set any extra colors when in text mode */
                    if (Bda->VideoMode <= 0x03) break;

                    VgaSetSinglePaletteRegister(0x00, Index);

                    Index = (Bda->CrtColorPaletteMask & 0x10) | 0x02 | ((Bda->CrtColorPaletteMask & 0x20) >> 5);

                    VgaSetSinglePaletteRegister(0x01, Index);
                    Index += 2;
                    VgaSetSinglePaletteRegister(0x02, Index);
                    Index += 2;
                    VgaSetSinglePaletteRegister(0x03, Index);
#else
                    /* Background/Border Color is modifiable via the first index */
                    VgaSetSinglePaletteRegister(0x00, getBL());
#endif

                    /* Enable screen and disable palette access */
                    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
                    IOWriteB(VGA_AC_INDEX, 0x20);
                    break;
                }

                case 0x01: /* Set Palette */
                {
                    BYTE Index = getBL();

                    /* See: http://www.bioscentral.com/misc/bda.htm */
                    /* Reset bit 5: foreground colors index (0: green/red/yellow; 1: cyan/magenta/white) */
                    Bda->CrtColorPaletteMask = (Bda->CrtColorPaletteMask & 0xDF) | ((Index & 1) ? 0x20 : 0x00);

                    /* Don't set any extra colors when in text mode */
                    if (Bda->VideoMode <= 0x03) break;

                    Index = (Bda->CrtColorPaletteMask & 0x10) | 0x02 | Index;

                    VgaSetSinglePaletteRegister(0x01, Index);
                    Index += 2;
                    VgaSetSinglePaletteRegister(0x02, Index);
                    Index += 2;
                    VgaSetSinglePaletteRegister(0x03, Index);

                    /* Enable screen and disable palette access */
                    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
                    IOWriteB(VGA_AC_INDEX, 0x20);
                    break;
                }

                default:
                    DPRINT1("BIOS Function INT 10h, AH = 0Bh, BH = 0x%02X NOT IMPLEMENTED\n",
                            getAH(), getBH());
                    break;
            }

            break;
        }

        /* Teletype Output */
        case 0x0E:
        {
            BYTE Page = getBH();

            /* Validate the selected video page */
            if (Page == 0xFF) // Special case: use the current video page
                Page = Bda->VideoPage;
            else if (Page >= BIOS_MAX_PAGES)
                break;

            VidBiosPrintCharacter(getAL(), getBL(), !IS_TEXT_MODE(Bda->VideoMode), Page);
            break;
        }

        /* Get Current Video Mode */
        case 0x0F:
        {
            setAX(MAKEWORD(VidBiosGetVideoMode(), Bda->ScreenColumns));
            setBH(Bda->VideoPage);
            break;
        }

        /* Palette Control */
        case 0x10:
        {
            switch (getAL())
            {
                /* Set Single Palette Register */
                case 0x00:
                {
                    VgaSetSinglePaletteRegister(getBL(), getBH());

                    /* Enable screen and disable palette access */
                    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
                    IOWriteB(VGA_AC_INDEX, 0x20);
                    break;
                }

                /* Set Overscan Color */
                case 0x01:
                {
                    VgaSetSinglePaletteRegister(VGA_AC_OVERSCAN_REG, getBH());

                    /* Enable screen and disable palette access */
                    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
                    IOWriteB(VGA_AC_INDEX, 0x20);
                    break;
                }

                /* Set All Palette Registers */
                case 0x02:
                {
                    UINT i;
                    LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());

                    /* Set the palette registers */
                    for (i = 0; i <= VGA_AC_PAL_F_REG; i++)
                    {
                        VgaSetSinglePaletteRegister(i, Buffer[i]);
                    }

                    /* Set the overscan register */
                    // VgaSetSinglePaletteRegister(VGA_AC_OVERSCAN_REG, Buffer[VGA_AC_PAL_F_REG + 1]);
                    IOReadB(VGA_INSTAT1_READ);
                    IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
                    IOWriteB(VGA_AC_WRITE, Buffer[VGA_AC_PAL_F_REG + 1]);

                    /* Enable screen and disable palette access */
                    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
                    IOWriteB(VGA_AC_INDEX, 0x20);
                    break;
                }

                /* Toggle Intensity/Blinking Bit */
                case 0x03:
                {
                    /* Read the old AC mode control register value */
                    BYTE VgaAcControlReg;

                    IOReadB(VGA_INSTAT1_READ);
                    IOWriteB(VGA_AC_INDEX, VGA_AC_CONTROL_REG);
                    VgaAcControlReg = IOReadB(VGA_AC_READ);

                    /* Toggle the blinking bit and write the new value */
                    if (getBL())
                    {
                        VgaAcControlReg |= VGA_AC_CONTROL_BLINK;
                        Bda->CrtModeControl |= (1 << 5);
                    }
                    else
                    {
                        VgaAcControlReg &= ~VGA_AC_CONTROL_BLINK;
                        Bda->CrtModeControl &= ~(1 << 5);
                    }

                    IOReadB(VGA_INSTAT1_READ);
                    IOWriteB(VGA_AC_INDEX, VGA_AC_CONTROL_REG);
                    IOWriteB(VGA_AC_WRITE, VgaAcControlReg);

                    /* Enable screen and disable palette access */
                    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
                    IOWriteB(VGA_AC_INDEX, 0x20);
                    break;
                }

                /* Get Single Palette Register */
                case 0x07:
                {
                    /* Write the index */
                    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
                    IOWriteB(VGA_AC_INDEX, getBL());

                    /* Read the data */
                    setBH(IOReadB(VGA_AC_READ));

                    /* Enable screen and disable palette access */
                    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
                    IOWriteB(VGA_AC_INDEX, 0x20);
                    break;
                }

                /* Get Overscan Color */
                case 0x08:
                {
                    /* Write the index */
                    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
                    IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);

                    /* Read the data */
                    setBH(IOReadB(VGA_AC_READ));

                    /* Enable screen and disable palette access */
                    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
                    IOWriteB(VGA_AC_INDEX, 0x20);
                    break;
                }

                /* Get All Palette Registers */
                case 0x09:
                {
                    UINT i;
                    LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());

                    /* Get the palette registers */
                    for (i = 0; i <= VGA_AC_PAL_F_REG; i++)
                    {
                        /* Write the index */
                        IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
                        IOWriteB(VGA_AC_INDEX, i);

                        /* Read the data */
                        Buffer[i] = IOReadB(VGA_AC_READ);
                    }

                    /* Get the overscan register */
                    IOReadB(VGA_INSTAT1_READ);
                    IOWriteB(VGA_AC_INDEX, VGA_AC_OVERSCAN_REG);
                    Buffer[VGA_AC_PAL_F_REG + 1] = IOReadB(VGA_AC_READ);

                    /* Enable screen and disable palette access */
                    IOReadB(VGA_INSTAT1_READ); // Put the AC register into index state
                    IOWriteB(VGA_AC_INDEX, 0x20);
                    break;
                }

                /* Set Individual DAC Register */
                case 0x10:
                {
                    /* Write the index */
                    // Certainly in BL and not in BX as said by Ralf Brown...
                    IOWriteB(VGA_DAC_WRITE_INDEX, getBL());

                    /* Write the data in this order: Red, Green, Blue */
                    IOWriteB(VGA_DAC_DATA, getDH());
                    IOWriteB(VGA_DAC_DATA, getCH());
                    IOWriteB(VGA_DAC_DATA, getCL());

                    break;
                }

                /* Set Block of DAC Registers */
                case 0x12:
                {
                    UINT i;
                    LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());

                    /* Write the index */
                    // Certainly in BL and not in BX as said by Ralf Brown...
                    IOWriteB(VGA_DAC_WRITE_INDEX, getBL());

                    for (i = 0; i < getCX(); i++)
                    {
                        /* Write the data in this order: Red, Green, Blue */
                        IOWriteB(VGA_DAC_DATA, *Buffer++);
                        IOWriteB(VGA_DAC_DATA, *Buffer++);
                        IOWriteB(VGA_DAC_DATA, *Buffer++);
                    }

                    break;
                }

                /* Set Video DAC Color Page */
                case 0x13:
                {
                    if (getBL() == 0)
                    {
                        /* Set the highest bit of the AC Mode Control register to BH */
                        IOReadB(VGA_INSTAT1_READ);
                        IOWriteB(VGA_AC_INDEX, VGA_AC_CONTROL_REG);
                        IOWriteB(VGA_AC_WRITE, (IOReadB(VGA_AC_READ) & 0x7F) | (getBH() << 7));
                    }
                    else if (getBL() == 1)
                    {
                        /* Set the AC Color Select register to BH */
                        IOReadB(VGA_INSTAT1_READ);
                        IOWriteB(VGA_AC_INDEX, VGA_AC_COLOR_SEL_REG);
                        IOWriteB(VGA_AC_WRITE, getBH());
                    }
                    else
                    {
                        DPRINT1("BIOS Palette Control Sub-sub-command BL = 0x%02X INVALID\n", getBL());
                    }

                    break;
                }

                /* Get Individual DAC Register */
                case 0x15:
                {
                    /* Write the index */
                    IOWriteB(VGA_DAC_READ_INDEX, getBL());

                    /* Read the data in this order: Red, Green, Blue */
                    setDH(IOReadB(VGA_DAC_DATA));
                    setCH(IOReadB(VGA_DAC_DATA));
                    setCL(IOReadB(VGA_DAC_DATA));

                    break;
                }

                /* Get Block of DAC Registers */
                case 0x17:
                {
                    UINT i;
                    LPBYTE Buffer = SEG_OFF_TO_PTR(getES(), getDX());

                    /* Write the index */
                    // Certainly in BL and not in BX as said by Ralf Brown...
                    IOWriteB(VGA_DAC_READ_INDEX, getBL());

                    for (i = 0; i < getCX(); i++)
                    {
                        /* Write the data in this order: Red, Green, Blue */
                        *Buffer++ = IOReadB(VGA_DAC_DATA);
                        *Buffer++ = IOReadB(VGA_DAC_DATA);
                        *Buffer++ = IOReadB(VGA_DAC_DATA);
                    }

                    break;
                }

                /* Set PEL Mask */
                case 0x18:
                {
                    IOWriteB(VGA_DAC_MASK, getBL());
                    break;
                }

                /* Get PEL Mask */
                case 0x19:
                {
                    setBL(IOReadB(VGA_DAC_MASK));
                    break;
                }

                default:
                {
                    DPRINT1("BIOS Palette Control Sub-command AL = 0x%02X NOT IMPLEMENTED\n",
                            getAL());
                    break;
                }
            }

            break;
        }

        /* Font Control */
        case 0x11:
        {
            switch (getAL())
            {
                // FIXME: At the moment we support only graphics-mode functions!

                /* Load User-specified Patterns (Character Set) for Text Mode */
                case 0x00:
                case 0x10: // FIXME: 0x1x performs a full mode reset
                {
                    // FIXME: BL == ??

                    /* Write the default font to the VGA font plane */
                    // VgaWriteTextModeFont(0, Font8x8, ARRAYSIZE(Font8x8) / VGA_FONT_CHARACTERS);

                    UNIMPLEMENTED;
                    break;
                }

                /* Load ROM Monochrome 8x14 Patterns (Character Set) for Text Mode */
                case 0x01:
                case 0x11: // FIXME: 0x1x performs a full mode reset
                {
                    // FIXME: BL == ??

                    /* Write the default font to the VGA font plane */
                    VgaWriteTextModeFont(0, Font8x14, ARRAYSIZE(Font8x14) / VGA_FONT_CHARACTERS);

                    UNIMPLEMENTED;
                    break;
                }

                /* Load ROM 8x8 Double-dot Patterns (Character Set) for Text Mode */
                case 0x02:
                case 0x12: // FIXME: 0x1x performs a full mode reset
                {
                    // FIXME: BL == ??

                    /* Write the default font to the VGA font plane */
                    VgaWriteTextModeFont(0, Font8x8, ARRAYSIZE(Font8x8) / VGA_FONT_CHARACTERS);

                    UNIMPLEMENTED;
                    break;
                }

                /* Load ROM 8x16 Character Set for Text Mode */
                case 0x04:
                case 0x14: // FIXME: 0x1x performs a full mode reset
                {
                    // FIXME: BL == ??

                    /* Write the default font to the VGA font plane */
                    VgaWriteTextModeFont(0, Font8x16, ARRAYSIZE(Font8x16) / VGA_FONT_CHARACTERS);

                    UNIMPLEMENTED;
                    break;
                }

                /* Set User 8x8 Graphics Chars (Setup INT 1Fh Vector) */
                case 0x20:
                {
                    /* Update the BIOS INT 1Fh vector to user-defined ES:BP pointer */
                    // Far pointer to the 8x8 characters 80h-FFh
                    ((PULONG)BaseAddress)[0x1F] = MAKELONG(getBP(), getES());
                    break;
                }

                /* Set User Graphics Characters */
                case 0x21:
                {
                    /*
                     * Update the BIOS INT 43h vector (far pointer
                     * to the character range 00h-...)
                     */
                    ((PULONG)BaseAddress)[0x43] = MAKELONG(getBP(), getES());

                    /* Update BDA */
                    Bda->CharacterHeight = getCX();
                    switch (getBL())
                    {
                        case 0x00: Bda->ScreenRows = getDL()-1; break;
                        case 0x01: Bda->ScreenRows = 13;        break;
                        case 0x03: Bda->ScreenRows = 42;        break;
                        case 0x02:
                        default  : Bda->ScreenRows = 24;        break;
                    }

                    break;
                }

                /* Setup ROM 8x14 Font for Graphics Mode */
                case 0x22:
                {
                    /*
                     * Update the BIOS INT 43h vector (far pointer
                     * to the character range 00h-...)
                     */
                    ((PULONG)BaseAddress)[0x43] = MAKELONG(FONT_8x14_OFFSET, VIDEO_BIOS_DATA_SEG);

                    /* Update BDA */
                    Bda->CharacterHeight = 14;
                    switch (getBL())
                    {
                        case 0x00: Bda->ScreenRows = getDL()-1; break;
                        case 0x01: Bda->ScreenRows = 13;        break;
                        case 0x03: Bda->ScreenRows = 42;        break;
                        case 0x02:
                        default  : Bda->ScreenRows = 24;        break;
                    }

                    break;
                }

                /* Setup ROM 8x8 Font for Graphics Mode */
                case 0x23:
                {
                    /*
                     * Update the BIOS INT 43h vector (far pointer
                     * to the character range 00h-...)
                     */
                    ((PULONG)BaseAddress)[0x43] = MAKELONG(FONT_8x8_OFFSET, VIDEO_BIOS_DATA_SEG);

                    /* Update BDA */
                    Bda->CharacterHeight = 8;
                    switch (getBL())
                    {
                        case 0x00: Bda->ScreenRows = getDL()-1; break;
                        case 0x01: Bda->ScreenRows = 13;        break;
                        case 0x03: Bda->ScreenRows = 42;        break;
                        case 0x02:
                        default  : Bda->ScreenRows = 24;        break;
                    }

                    break;
                }

                /* Setup ROM 8x16 Font for Graphics Mode */
                case 0x24:
                {
                    /*
                     * Update the BIOS INT 43h vector (far pointer
                     * to the character range 00h-...).
                     */
                    ((PULONG)BaseAddress)[0x43] = MAKELONG(FONT_8x16_OFFSET, VIDEO_BIOS_DATA_SEG);

                    /* Update BDA */
                    Bda->CharacterHeight = 16;
                    switch (getBL())
                    {
                        case 0x00: Bda->ScreenRows = getDL()-1; break;
                        case 0x01: Bda->ScreenRows = 13;        break;
                        case 0x03: Bda->ScreenRows = 42;        break;
                        case 0x02:
                        default  : Bda->ScreenRows = 24;        break;
                    }

                    break;
                }

                /* Get Current Character Font Information */
                case 0x30:
                {
                    ULONG Address = NULL32;

                    switch (getBH())
                    {
                        /* 00h - INT 0x1F pointer */
                        case 0x00:
                            Address = ((PULONG)BaseAddress)[0x1F];
                            break;

                        /* 01h - INT 0x43 pointer */
                        case 0x01:
                            Address = ((PULONG)BaseAddress)[0x43];
                            break;

                        /* 02h - 8x14 font */
                        case 0x02:
                            Address = MAKELONG(FONT_8x14_OFFSET, VIDEO_BIOS_DATA_SEG);
                            break;

                        /* 03h - 8x8 font */
                        case 0x03:
                            Address = MAKELONG(FONT_8x8_OFFSET, VIDEO_BIOS_DATA_SEG);
                            break;

                        /* 04h - 8x8 font, upper half */
                        case 0x04:
                            Address = MAKELONG(FONT_8x8_HIGH_OFFSET, VIDEO_BIOS_DATA_SEG);
                            break;

                        /* 05h - NOT IMPLEMENTED - 9x14 font */
                        case 0x05:
                            break;

                        /* 06h - 8x16 font */
                        case 0x06:
                            Address = MAKELONG(FONT_8x16_OFFSET, VIDEO_BIOS_DATA_SEG);
                            break;

                        /* 07h - NOT IMPLEMENTED - 9x16 font */
                        case 0x07:
                            break;

                        default:
                            DPRINT1("INT 10h, AL=30h Function BH = 0x%02X NOT IMPLEMENTED\n",
                                    getBH());
                    }

                    /* Return the data */
                    setES(HIWORD(Address));
                    setBP(LOWORD(Address));
                    setCX(Bda->CharacterHeight);
                    setDL(Bda->ScreenRows);

                    break;
                }

                default:
                {
                    DPRINT1("BIOS Font Control Sub-command AL = 0x%02X NOT IMPLEMENTED\n",
                            getAL());
                }
            }

            break;
        }

        /* Alternate Function Select */
        case 0x12:
        {
            switch (getBL())
            {
                /* Get EGA/VGA Information */
                case 0x10:
                {
                    setBH((Bda->VGAOptions  & 0x02) >> 1);  /* Color (0) or monochrome (1) display */
                    setBL((Bda->VGAOptions  & 0x60) >> 5);  /* Video RAM size */
                    setCH((Bda->VGASwitches & 0xF0) >> 4);  /* Features settings */
                    setCL( Bda->VGASwitches & 0x0F);        /* Switches settings */
                    break;
                }

                /* Enable/Disable Cursor Emulation */
                case 0x34:
                {
                    BYTE State = getAL();

                    /* Check for validity */
                    if (State > 1) break;

                    /*
                     * Enable (State == 0) or disable (State == 1) cursor emulation.
                     * Please read the WARNING in the 'VidBiosSetCursorShape'
                     * function for more details.
                     */
                    Bda->VGAOptions = (Bda->VGAOptions & 0xFE) | (State & 0x01);

                    /* Return success */
                    setAL(0x12);
                    break;
                }

                /* Enable/Disable screen refresh */
                case 0x36:
                {
                    BYTE State = getAL();
                    BYTE Clocking;

                    /* Check for validity */
                    if (State > 1) break;

                    /* Turn the video on (State == 0) or off (State == 1) */
                    IOWriteB(VGA_SEQ_INDEX, VGA_SEQ_CLOCK_REG);
                    Clocking = IOReadB(VGA_SEQ_DATA);

                    if (State == 0)
                        Clocking &= ~VGA_SEQ_CLOCK_SD;
                    else
                        Clocking |= VGA_SEQ_CLOCK_SD;

                    IOWriteB(VGA_SEQ_DATA, Clocking);

                    /* Return success */
                    setAL(0x12);
                    break;
                }

                default:
                {
                    DPRINT1("BIOS Function INT 10h, AH = 12h (Alternate Function Select), BX = 0x%04X NOT IMPLEMENTED\n",
                            getBX());
                    break;
                }
            }

            break;
        }

        /* Write String */
        case 0x13:
        {
            PCHAR String = (PCHAR)SEG_OFF_TO_PTR(getES(), getBP());
            WORD Counter = getCX();
            BYTE Row, Column;
            BYTE OldRow, OldColumn;
            CHAR Character;
            BYTE Attribute = getBL(); // Default attribute in case the string contains only characters.
            BYTE Page = getBH();
            BYTE Flags = getAL();

            /* Validate the selected video page */
            if (Page == 0xFF) // Special case: use the current video page
                Page = Bda->VideoPage;
            else if (Page >= BIOS_MAX_PAGES)
                break;

            /* Get the original cursor position */
            VidBiosGetCursorPosition(&OldRow, &OldColumn, Page);

            /* Set the new cursor position */
            Row    = getDH();
            Column = getDL();
            if (Row == 0xFF) // Special case: use the current cursor position
            {
                Row    = OldRow;
                Column = OldColumn;
            }
            VidBiosSetCursorPosition(Row, Column, Page);

            while (Counter-- > 0)
            {
                Character = *String++;
                if (Flags & 0x02) Attribute = *String++;
                VidBiosPrintCharacter(Character, Attribute, TRUE, Page);
            }

            /* Reset the cursor position to its original value if we don't want to update it */
            if (!(Flags & 0x01)) VidBiosSetCursorPosition(OldRow, OldColumn, Page);

            break;
        }

        /* Get/Set Display combination code */
        case 0x1A:
        {
            switch (getAL())
            {
                case 0x00: /* Get Display combination code */
                {
                    setBL(Bda->VGADccIDActive);
                    setBH(0x00); // No alternate display

                    /* Return success */
                    setAL(0x1A);
                    break;
                }
                case 0x01: /* Set Display combination code */
                {
                    DPRINT1("Set Display combination code - Unsupported\n");
                    break;
                }
                default:
                    break;
            }
            break;
        }

        /* Functionality/State Information (VGA) */
        case 0x1B:
        {
            PVGA_DYNAMIC_FUNC_TABLE Table = SEG_OFF_TO_PTR(getES(), getDI());

            /* Check for only supported subfunction */
            if (getBX() != 0x0000)
            {
                DPRINT1("INT 10h, AH=1Bh, unsupported subfunction 0x%04x\n", getBX());
                break;
            }

            /* Fill the VGA dynamic functionality table with our information */

            Table->StaticFuncTablePtr = MAKELONG(VIDEO_STATE_INFO_OFFSET, VIDEO_BIOS_DATA_SEG);

            Table->VideoMode       = Bda->VideoMode;
            Table->ScreenColumns   = Bda->ScreenColumns;
            Table->VideoPageSize   = Bda->VideoPageSize;
            Table->VideoPageOffset = Bda->VideoPageOffset;
            RtlCopyMemory(Table->CursorPosition, Bda->CursorPosition, sizeof(Bda->CursorPosition));
            Table->CursorEndLine   = Bda->CursorEndLine;
            Table->CursorStartLine = Bda->CursorStartLine;
            Table->VideoPage       = Bda->VideoPage;
            Table->CrtBasePort     = Bda->CrtBasePort;
            Table->CrtModeControl  = Bda->CrtModeControl;
            Table->CrtColorPaletteMask = Bda->CrtColorPaletteMask;
            Table->ScreenRows      = Bda->ScreenRows;
            Table->CharacterHeight = Bda->CharacterHeight;

            Table->VGADccIDActive    = Bda->VGADccIDActive;
            Table->VGADccIDAlternate = 0x00; // No alternate display
            // Table->CurrModeSupportedColorsNum;
            // Table->CurrModeSupportedPagesNum;
            // Table->Scanlines;
            // Table->PrimaryCharTable;
            // Table->SecondaryCharTable;
            // Table->VGAFlags;
            Table->VGAAvailMemory = (Bda->VGAOptions & 0x60) >> 5;
            // Table->VGASavePtrStateFlags;
            // Table->VGADispInfo;
            UNIMPLEMENTED;

            /* Return success */
            setAL(0x1B);
            break;
        }

        /* VESA BIOS Extensions */
        case 0x4F:
        {
            if (VbeInitialized) VbeService(Stack);
            break;
        }

        default:
        {
            DPRINT1("BIOS Function INT 10h, AH = 0x%02X, AL = 0x%02X, BH = 0x%02X NOT IMPLEMENTED\n",
                    getAH(), getAL(), getBH());
        }
    }
}


/*
 * Those attach / detach functions are work-in-progress
 */

static BOOL Attached = TRUE;

VOID VidBiosAttachToConsole(VOID)
{
    if (!Attached)
    {
        VgaAttachToConsole();
        Attached = TRUE;
    }

    /* Refresh display */
    VgaRefreshDisplay();
    VidBiosSyncCursorPosition();
}

VOID VidBiosDetachFromConsole(VOID)
{
    if (!Attached) return;

    /* Refresh display */
    VgaRefreshDisplay();

    /* Detach from the console */
    VgaDetachFromConsole();
    Attached = FALSE;
}

VOID VidBiosPost(VOID)
{
    /*
     * Initialize VGA BIOS32 RAM dynamic data
     */

    /* Some vectors are in fact addresses to tables */
    ((PULONG)BaseAddress)[0x1D] = NULL32; // Video Parameter Tables
    // Far pointer to the 8x8 graphics font for the 8x8 characters 80h-FFh
    ((PULONG)BaseAddress)[0x1F] = MAKELONG(FONT_8x8_HIGH_OFFSET, VIDEO_BIOS_DATA_SEG);
    // Far pointer to the character table (EGA, MCGA, VGA) for the 8x16 characters 00h-...
    ((PULONG)BaseAddress)[0x43] = MAKELONG(FONT_8x16_OFFSET, VIDEO_BIOS_DATA_SEG);
    ((PULONG)BaseAddress)[0x44] = NULL32; // ROM BIOS Character Font, Characters 00h-7Fh (PCjr)

    /* Relocated services by the BIOS (when needed) */
    ((PULONG)BaseAddress)[0x42] = NULL32; // Relocated Default INT 10h Video Services
    ((PULONG)BaseAddress)[0x6D] = NULL32; // Video BIOS Entry Point

    //
    // FIXME: At the moment we always set a VGA mode. In the future,
    // we should set this mode **only** when:
    // - an app starts to use directly the video memory
    //   (that should be done in emulator.c)
    // - or starts to use non-stream I/O interrupts
    //   (that should be done here, or maybe in VGA ??)
    //

    Bda->CrtModeControl      = 0x00;
    Bda->CrtColorPaletteMask = 0x00;
    Bda->VGADccIDActive      = 0x08; // VGA w/ color analog active display

    /* Set the default video mode */
    VidBiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE);

    /* Synchronize our cursor position with VGA */
    VidBiosSyncCursorPosition();

    /* Register the BIOS 32-bit Interrupts */
    RegisterBiosInt32(BIOS_VIDEO_INTERRUPT, VidBiosVideoService);

    /* Vectors that should be implemented */
    RegisterBiosInt32(0x42, NULL); // Relocated Default INT 10h Video Services
    RegisterBiosInt32(0x6D, NULL); // Video BIOS Entry Point

    /* Initialize VBE */
    VbeInitialized = VbeInitialize();
    if (!VbeInitialized) DPRINT1("Couldn't initialize VBE!\n");
}

BOOLEAN VidBiosInitialize(VOID)
{
    UCHAR Checksum;

    /*
     * Initialize VGA BIOS32 static data
     */

    /* This is a ROM of size 'VIDEO_BIOS_ROM_SIZE' */
    *(PWORD)(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, 0x0000)) = 0xAA55;
    *(PBYTE)(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, 0x0002)) = VIDEO_BIOS_ROM_SIZE / 512; // Size in blocks of 512 bytes

    /* Bootstrap code */
    *(PWORD)(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, 0x0003)) = 0x90CB; // retf, nop
    // RtlCopyMemory(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, 0xFFF0), Bootstrap, sizeof(Bootstrap));

    /* Video BIOS Information */
    RtlCopyMemory(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, 0x0005), BiosInfo, sizeof(BiosInfo)-1);

    /* Initialize the VGA static function table */
    VgaStaticFuncTable = SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, VIDEO_STATE_INFO_OFFSET);
    RtlZeroMemory(VgaStaticFuncTable, sizeof(*VgaStaticFuncTable));
    VgaStaticFuncTable->SupportedModes[0] = 0xFF; // Modes 0x00 to 0x07 supported
    VgaStaticFuncTable->SupportedModes[1] = 0xFF; // Modes 0x08 to 0x0F supported
    VgaStaticFuncTable->SupportedModes[2] = 0x0F; // Modes 0x10 to 0x13 supported
    VgaStaticFuncTable->SupportedScanlines   = 0x07; // Scanlines 200, 350 and 400 supported
    VgaStaticFuncTable->TextCharBlocksNumber = 0;
    VgaStaticFuncTable->MaxActiveTextCharBlocksNumber = 0;
    VgaStaticFuncTable->VGAFuncSupportFlags = 0x0CFD; // See: http://www.ctyme.com/intr/rb-0221.htm#Table46
    VgaStaticFuncTable->VGASavePtrFuncFlags = 0x18;   // See: http://www.ctyme.com/intr/rb-0221.htm#Table47

    /* Fill the font tables */
    RtlMoveMemory(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, FONT_8x8_OFFSET),
                  Font8x8, sizeof(Font8x8));
    RtlMoveMemory(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, FONT_8x16_OFFSET),
                  Font8x16, sizeof(Font8x16));
    RtlMoveMemory(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, FONT_8x14_OFFSET),
                  Font8x14, sizeof(Font8x14));

    /* Make another copy of the lower half of the 8x8 font at F000:FA6E for compatibility */
    RtlMoveMemory(SEG_OFF_TO_PTR(BIOS_SEGMENT, FONT_8x8_COMPAT_OFFSET), Font8x8, sizeof(Font8x8) / 2);

    VidBios32Initialize();

    /* Compute the ROM checksum and store it */
    *(PBYTE)(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, VIDEO_BIOS_ROM_SIZE - 1)) = 0x00;
    Checksum = CalcRomChecksum(TO_LINEAR(VIDEO_BIOS_DATA_SEG, 0x0000), VIDEO_BIOS_ROM_SIZE);
    *(PBYTE)(SEG_OFF_TO_PTR(VIDEO_BIOS_DATA_SEG, VIDEO_BIOS_ROM_SIZE - 1)) = (0xFF - Checksum + 1) & 0xFF;

    WriteProtectRom((PVOID)TO_LINEAR(VIDEO_BIOS_DATA_SEG, 0x0000),
                    VIDEO_BIOS_ROM_SIZE);

    return TRUE;
}

VOID VidBiosCleanup(VOID)
{
}

/* EOF */
